From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp40.i.mail.ru (smtp40.i.mail.ru [94.100.177.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id E352B4696C3 for ; Thu, 2 Apr 2020 09:38:21 +0300 (MSK) From: "Alexander V. Tikhonov" Date: Thu, 2 Apr 2020 09:38:15 +0300 Message-Id: Subject: [Tarantool-patches] [PATCH v1] Divide test box/net.box List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Oleg Piskunov , Sergey Bronnikov Cc: tarantool-patches@dev.tarantool.org box/net.box_bad_argument_gh-594.test.lua box/net.box_call_blocks_gh-946.test.lua box/net.box_collectgarbage_gh-3107.test.lua box/net.box_connect_triggers.test.lua box/net.box_console_connections_gh-2677.test.lua box/net.box_count_inconsistent_gh-3262.test.lua box/net.box_discard_gh-3107.test.lua box/net.box_disconnect_gh-3859.test.lua box/net.box_fiber-async_gh-3107.test.lua box/net.box_field_names_gh-2978.test.lua box/net.box_get_connection_object.test.lua box/net.box_gibberish_gh-3900.test.lua box/net.box_huge_data_gh-983.test.lua box/net.box_incompatible_index-gh-1729.test.lua box/net.box_incorrect_iterator_gh-841.test.lua box/net.box_index_unique_flag_gh-4091.test.lua box/net.box_iproto_hangs_gh-3464.test.lua box/net.box_is_nullable_gh-3256.test.lua box/net.box_leaks_gh-3629.test.lua box/net.box_log_corrupted_rows_gh-4040.test.lua box/net.box_long-poll_input_gh-3400.test.lua box/net.box_methods_gh-3107.test.lua box/net.box_msgpack_gh-2195.test.lua box/net.box_on_schema_reload-gh-1904.test.lua box/net.box_password_gh-1545.test.lua box/net.box_permissions.test.lua box/net.box_pseudo_objects_gh-2401.test.lua box/net.box_raw_response_gh-3107.test.lua box/net.box_readahead_gh-3958.test.lua box/net.box_reconnect_after_gh-3164.test.lua box/net.box_reconnect_after.test.lua box/net.box_reload_schema_gh-636.test.lua box/net.box_remote_method_gh-544.test.lua box/net.box_roll_back_gh-822.test.lua box/net.box_schema_change_gh-2666.test.lua box/net.box_schema_change_gh-3107.test.lua box/net.box_session_type_gh-2642.test.lua box/net.box_space_format_gh-2402.test.lua box/net.box_timeout_gh-1533.test.lua box/net.box_timeout-gh-3107.test.lua box/net.box_upsert_gh-970.test.lua box/net.box_wait_connected_gh-3856.test.lua --- Github: https://github.com/tarantool/tarantool/tree/avtikhon/divide_tests test/box/gh-3107_rest1_net.box.result | 119 + test/box/net.box.result | 3932 ----------------- test/box/net.box.test.lua | 1585 ------- test/box/net.box_bad_argument_gh-594.result | 38 + test/box/net.box_bad_argument_gh-594.test.lua | 17 + test/box/net.box_call_blocks_gh-946.result | 124 + test/box/net.box_call_blocks_gh-946.test.lua | 67 + .../box/net.box_collectgarbage_gh-3107.result | 120 + .../net.box_collectgarbage_gh-3107.test.lua | 44 + test/box/net.box_connect_triggers.result | 82 + test/box/net.box_connect_triggers.test.lua | 27 + ...net.box_console_connections_gh-2677.result | 95 + ...t.box_console_connections_gh-2677.test.lua | 39 + .../net.box_count_inconsistent_gh-3262.result | 488 ++ ...et.box_count_inconsistent_gh-3262.test.lua | 182 + test/box/net.box_discard_gh-3107.result | 119 + test/box/net.box_discard_gh-3107.test.lua | 44 + test/box/net.box_disconnect_gh-3859.result | 113 + test/box/net.box_disconnect_gh-3859.test.lua | 50 + test/box/net.box_fiber-async_gh-3107.result | 115 + test/box/net.box_fiber-async_gh-3107.test.lua | 42 + test/box/net.box_field_names_gh-2978.result | 101 + test/box/net.box_field_names_gh-2978.test.lua | 29 + test/box/net.box_get_connection_object.result | 40 + .../net.box_get_connection_object.test.lua | 19 + test/box/net.box_gibberish_gh-3900.result | 31 + test/box/net.box_gibberish_gh-3900.test.lua | 13 + test/box/net.box_huge_data_gh-983.result | 30 + test/box/net.box_huge_data_gh-983.test.lua | 16 + .../net.box_incompatible_index-gh-1729.result | 99 + ...et.box_incompatible_index-gh-1729.test.lua | 33 + .../net.box_incorrect_iterator_gh-841.result | 497 +++ ...net.box_incorrect_iterator_gh-841.test.lua | 182 + .../net.box_index_unique_flag_gh-4091.result | 28 + ...net.box_index_unique_flag_gh-4091.test.lua | 15 + test/box/net.box_iproto_hangs_gh-3464.result | 31 + .../box/net.box_iproto_hangs_gh-3464.test.lua | 13 + test/box/net.box_is_nullable_gh-3256.result | 97 + test/box/net.box_is_nullable_gh-3256.test.lua | 36 + test/box/net.box_leaks_gh-3629.result | 51 + test/box/net.box_leaks_gh-3629.test.lua | 20 + .../net.box_log_corrupted_rows_gh-4040.result | 72 + ...et.box_log_corrupted_rows_gh-4040.test.lua | 31 + .../net.box_long-poll_input_gh-3400.result | 35 + .../net.box_long-poll_input_gh-3400.test.lua | 19 + test/box/net.box_methods_gh-3107.result | 277 ++ test/box/net.box_methods_gh-3107.test.lua | 96 + test/box/net.box_msgpack_gh-2195.result | 527 +++ test/box/net.box_msgpack_gh-2195.test.lua | 192 + .../net.box_on_schema_reload-gh-1904.result | 102 + .../net.box_on_schema_reload-gh-1904.test.lua | 65 + test/box/net.box_password_gh-1545.result | 28 + test/box/net.box_password_gh-1545.test.lua | 10 + test/box/net.box_permissions.result | 186 + test/box/net.box_permissions.test.lua | 66 + .../box/net.box_pseudo_objects_gh-2401.result | 55 + .../net.box_pseudo_objects_gh-2401.test.lua | 23 + test/box/net.box_raw_response_gh-3107.result | 123 + .../box/net.box_raw_response_gh-3107.test.lua | 46 + test/box/net.box_readahead_gh-3958.result | 55 + test/box/net.box_readahead_gh-3958.test.lua | 29 + test/box/net.box_reconnect_after.result | 32 + test/box/net.box_reconnect_after.test.lua | 16 + .../net.box_reconnect_after_gh-3164.result | 119 + .../net.box_reconnect_after_gh-3164.test.lua | 52 + test/box/net.box_reload_schema_gh-636.result | 108 + .../box/net.box_reload_schema_gh-636.test.lua | 46 + test/box/net.box_remote_method_gh-544.result | 95 + .../box/net.box_remote_method_gh-544.test.lua | 40 + test/box/net.box_roll_back_gh-822.result | 68 + test/box/net.box_roll_back_gh-822.test.lua | 42 + test/box/net.box_schema_change_gh-2666.result | 79 + .../net.box_schema_change_gh-2666.test.lua | 28 + test/box/net.box_schema_change_gh-3107.result | 151 + .../net.box_schema_change_gh-3107.test.lua | 55 + test/box/net.box_session_type_gh-2642.result | 22 + .../box/net.box_session_type_gh-2642.test.lua | 11 + test/box/net.box_space_format_gh-2402.result | 49 + .../box/net.box_space_format_gh-2402.test.lua | 23 + test/box/net.box_timeout-gh-3107.result | 125 + test/box/net.box_timeout-gh-3107.test.lua | 47 + test/box/net.box_timeout_gh-1533.result | 89 + test/box/net.box_timeout_gh-1533.test.lua | 45 + test/box/net.box_upsert_gh-970.result | 49 + test/box/net.box_upsert_gh-970.test.lua | 16 + .../box/net.box_wait_connected_gh-3856.result | 20 + .../net.box_wait_connected_gh-3856.test.lua | 8 + 87 files changed, 6778 insertions(+), 5517 deletions(-) create mode 100644 test/box/gh-3107_rest1_net.box.result delete mode 100644 test/box/net.box.result delete mode 100644 test/box/net.box.test.lua create mode 100644 test/box/net.box_bad_argument_gh-594.result create mode 100644 test/box/net.box_bad_argument_gh-594.test.lua create mode 100644 test/box/net.box_call_blocks_gh-946.result create mode 100644 test/box/net.box_call_blocks_gh-946.test.lua create mode 100644 test/box/net.box_collectgarbage_gh-3107.result create mode 100644 test/box/net.box_collectgarbage_gh-3107.test.lua create mode 100644 test/box/net.box_connect_triggers.result create mode 100644 test/box/net.box_connect_triggers.test.lua create mode 100644 test/box/net.box_console_connections_gh-2677.result create mode 100644 test/box/net.box_console_connections_gh-2677.test.lua create mode 100644 test/box/net.box_count_inconsistent_gh-3262.result create mode 100644 test/box/net.box_count_inconsistent_gh-3262.test.lua create mode 100644 test/box/net.box_discard_gh-3107.result create mode 100644 test/box/net.box_discard_gh-3107.test.lua create mode 100644 test/box/net.box_disconnect_gh-3859.result create mode 100644 test/box/net.box_disconnect_gh-3859.test.lua create mode 100644 test/box/net.box_fiber-async_gh-3107.result create mode 100644 test/box/net.box_fiber-async_gh-3107.test.lua create mode 100644 test/box/net.box_field_names_gh-2978.result create mode 100644 test/box/net.box_field_names_gh-2978.test.lua create mode 100644 test/box/net.box_get_connection_object.result create mode 100644 test/box/net.box_get_connection_object.test.lua create mode 100644 test/box/net.box_gibberish_gh-3900.result create mode 100644 test/box/net.box_gibberish_gh-3900.test.lua create mode 100644 test/box/net.box_huge_data_gh-983.result create mode 100644 test/box/net.box_huge_data_gh-983.test.lua create mode 100644 test/box/net.box_incompatible_index-gh-1729.result create mode 100644 test/box/net.box_incompatible_index-gh-1729.test.lua create mode 100644 test/box/net.box_incorrect_iterator_gh-841.result create mode 100644 test/box/net.box_incorrect_iterator_gh-841.test.lua create mode 100644 test/box/net.box_index_unique_flag_gh-4091.result create mode 100644 test/box/net.box_index_unique_flag_gh-4091.test.lua create mode 100644 test/box/net.box_iproto_hangs_gh-3464.result create mode 100644 test/box/net.box_iproto_hangs_gh-3464.test.lua create mode 100644 test/box/net.box_is_nullable_gh-3256.result create mode 100644 test/box/net.box_is_nullable_gh-3256.test.lua create mode 100644 test/box/net.box_leaks_gh-3629.result create mode 100644 test/box/net.box_leaks_gh-3629.test.lua create mode 100644 test/box/net.box_log_corrupted_rows_gh-4040.result create mode 100644 test/box/net.box_log_corrupted_rows_gh-4040.test.lua create mode 100644 test/box/net.box_long-poll_input_gh-3400.result create mode 100644 test/box/net.box_long-poll_input_gh-3400.test.lua create mode 100644 test/box/net.box_methods_gh-3107.result create mode 100644 test/box/net.box_methods_gh-3107.test.lua create mode 100644 test/box/net.box_msgpack_gh-2195.result create mode 100644 test/box/net.box_msgpack_gh-2195.test.lua create mode 100644 test/box/net.box_on_schema_reload-gh-1904.result create mode 100644 test/box/net.box_on_schema_reload-gh-1904.test.lua create mode 100644 test/box/net.box_password_gh-1545.result create mode 100644 test/box/net.box_password_gh-1545.test.lua create mode 100644 test/box/net.box_permissions.result create mode 100644 test/box/net.box_permissions.test.lua create mode 100644 test/box/net.box_pseudo_objects_gh-2401.result create mode 100644 test/box/net.box_pseudo_objects_gh-2401.test.lua create mode 100644 test/box/net.box_raw_response_gh-3107.result create mode 100644 test/box/net.box_raw_response_gh-3107.test.lua create mode 100644 test/box/net.box_readahead_gh-3958.result create mode 100644 test/box/net.box_readahead_gh-3958.test.lua create mode 100644 test/box/net.box_reconnect_after.result create mode 100644 test/box/net.box_reconnect_after.test.lua create mode 100644 test/box/net.box_reconnect_after_gh-3164.result create mode 100644 test/box/net.box_reconnect_after_gh-3164.test.lua create mode 100644 test/box/net.box_reload_schema_gh-636.result create mode 100644 test/box/net.box_reload_schema_gh-636.test.lua create mode 100644 test/box/net.box_remote_method_gh-544.result create mode 100644 test/box/net.box_remote_method_gh-544.test.lua create mode 100644 test/box/net.box_roll_back_gh-822.result create mode 100644 test/box/net.box_roll_back_gh-822.test.lua create mode 100644 test/box/net.box_schema_change_gh-2666.result create mode 100644 test/box/net.box_schema_change_gh-2666.test.lua create mode 100644 test/box/net.box_schema_change_gh-3107.result create mode 100644 test/box/net.box_schema_change_gh-3107.test.lua create mode 100644 test/box/net.box_session_type_gh-2642.result create mode 100644 test/box/net.box_session_type_gh-2642.test.lua create mode 100644 test/box/net.box_space_format_gh-2402.result create mode 100644 test/box/net.box_space_format_gh-2402.test.lua create mode 100644 test/box/net.box_timeout-gh-3107.result create mode 100644 test/box/net.box_timeout-gh-3107.test.lua create mode 100644 test/box/net.box_timeout_gh-1533.result create mode 100644 test/box/net.box_timeout_gh-1533.test.lua create mode 100644 test/box/net.box_upsert_gh-970.result create mode 100644 test/box/net.box_upsert_gh-970.test.lua create mode 100644 test/box/net.box_wait_connected_gh-3856.result create mode 100644 test/box/net.box_wait_connected_gh-3856.test.lua diff --git a/test/box/gh-3107_rest1_net.box.result b/test/box/gh-3107_rest1_net.box.result new file mode 100644 index 000000000..d9c59d1cf --- /dev/null +++ b/test/box/gh-3107_rest1_net.box.result @@ -0,0 +1,119 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Check infinity timeout. +-- +ret = nil +--- +... +_ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async = true}):wait_result() end) +--- +... +finalize_long() +--- +... +while not ret do fiber.sleep(0.01) end +--- +... +ret +--- +- [1, 2, 3] +... +c:close() +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +c = net:connect(box.cfg.listen) +--- +... +future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true}) +--- +... +future:result() +--- +- null +- Response is not ready +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +future:wait_result(100) +--- +- [1, 2, 3] +... +c:close() +--- +... +-- +-- Check that is_async does not work on a closed connection. +-- +c:call('any_func', {}, {is_async = true}) +--- +- error: Connection closed +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +c = net:connect(box.cfg.listen) +--- +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box.result b/test/box/net.box.result deleted file mode 100644 index e3dabf7d9..000000000 --- a/test/box/net.box.result +++ /dev/null @@ -1,3932 +0,0 @@ -remote = require 'net.box' ---- -... -fiber = require 'fiber' ---- -... -log = require 'log' ---- -... -msgpack = require 'msgpack' ---- -... -env = require('test_run') ---- -... -test_run = env.new() ---- -... -test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") ---- -- true -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... -function x_select(cn, space_id, index_id, iterator, offset, limit, key, opts) - local ret = cn:_request('select', opts, nil, space_id, index_id, iterator, - offset, limit, key) - return ret -end -function x_fatal(cn) cn._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') end -test_run:cmd("setopt delimiter ''"); ---- -... -LISTEN = require('uri').parse(box.cfg.listen) ---- -... -space = box.schema.space.create('net_box_test_space') ---- -... -index = space:create_index('primary', { type = 'tree' }) ---- -... --- low level connection -log.info("create connection") ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service) ---- -... -log.info("state is %s", cn.state) ---- -... -cn:ping() ---- -- true -... -log.info("ping is done") ---- -... -cn:ping() ---- -- true -... -log.info("ping is done") ---- -... -cn:ping() ---- -- true -... --- check permissions -cn:call('unexists_procedure') ---- -- error: Execute access to function 'unexists_procedure' is denied for user 'guest' -... -function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end ---- -... -cn:call('test_foo', {'a', 'b', 'c'}) ---- -- error: Execute access to function 'test_foo' is denied for user 'guest' -... -cn:eval('return 2+2') ---- -- error: Execute access to universe '' is denied for user 'guest' -... -cn:close() ---- -... --- connect and call without usage access -box.schema.user.grant('guest','execute','universe') ---- -... -box.schema.user.revoke('guest','usage','universe') ---- -... -box.session.su("guest") ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service) ---- -... -cn:call('test_foo', {'a', 'b', 'c'}) ---- -- error: Usage access to universe '' is denied for user 'guest' -... -box.session.su("admin") ---- -... -box.schema.user.grant('guest','usage','universe') ---- -... -cn:close() ---- -... -cn = remote.connect(box.cfg.listen) ---- -... -cn:call('unexists_procedure') ---- -- error: Procedure 'unexists_procedure' is not defined -... -cn:call('test_foo', {'a', 'b', 'c'}) ---- -- [[{'a': 1}], [{'b': 2}], 'c'] -... -cn:call(nil, {'a', 'b', 'c'}) ---- -- error: Procedure 'nil' is not defined -... -cn:eval('return 2+2') ---- -- 4 -... -cn:eval('return 1, 2, 3') ---- -- 1 -- 2 -- 3 -... -cn:eval('return ...', {1, 2, 3}) ---- -- 1 -- 2 -- 3 -... -cn:eval('return { k = "v1" }, true, { xx = 10, yy = 15 }, nil') ---- -- {'k': 'v1'} -- true -- {'yy': 15, 'xx': 10} -- null -... -cn:eval('return nil') ---- -- null -... -cn:eval('return') ---- -... -cn:eval('error("exception")') ---- -- error: 'eval:1: exception' -... -cn:eval('box.error(0)') ---- -- error: Unknown error -... -cn:eval('!invalid expression') ---- -- error: 'eval:1: unexpected symbol near ''!''' -... --- box.commit() missing at return of CALL/EVAL -function no_commit() box.begin() fiber.sleep(0.001) end ---- -... -cn:call('no_commit') ---- -- error: Transaction is active at return from function -... -cn:eval('no_commit()') ---- -- error: Transaction is active at return from function -... -remote.self:eval('return 1+1, 2+2') ---- -- 2 -- 4 -... -remote.self:eval('return') ---- -... -remote.self:eval('error("exception")') ---- -- error: '[string "error("exception")"]:1: exception' -... -remote.self:eval('box.error(0)') ---- -- error: Unknown error -... -remote.self:eval('!invalid expression') ---- -- error: '[string "return !invalid expression"]:1: unexpected symbol near ''!''' -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- --- gh-822: net.box.call should roll back local transaction on error --- -_ = box.schema.space.create('gh822') ---- -... -_ = box.space.gh822:create_index('primary') ---- -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... --- rollback on invalid function -function rollback_on_invalid_function() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.call, remote.self, 'invalid_function') - return box.space.gh822:get(1) == nil -end; ---- -... -rollback_on_invalid_function(); ---- -- true -... --- rollback on call error -function test_error() error('Some error') end; ---- -... -function rollback_on_call_error() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.call, remote.self, 'test_error') - return box.space.gh822:get(1) == nil -end; ---- -... -rollback_on_call_error(); ---- -- true -... --- rollback on eval -function rollback_on_eval_error() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.eval, remote.self, "error('Some error')") - return box.space.gh822:get(1) == nil -end; ---- -... -rollback_on_eval_error(); ---- -- true -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -box.space.gh822:drop() ---- -... -box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -cn:close() ---- -... -cn = remote.connect(box.cfg.listen) ---- -... -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0xFFFFFFFF, 123) ---- -- [] -... -space:insert{123, 345} ---- -- [123, 345] -... -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0, 123) ---- -- [] -... -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 1, 123) ---- -- - [123, 345] -... -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 1, 1, 123) ---- -- [] -... -cn.space[space.id] ~= nil ---- -- true -... -cn.space.net_box_test_space ~= nil ---- -- true -... -cn.space.net_box_test_space ~= nil ---- -- true -... -cn.space.net_box_test_space.index ~= nil ---- -- true -... -cn.space.net_box_test_space.index.primary ~= nil ---- -- true -... -cn.space.net_box_test_space.index[space.index.primary.id] ~= nil ---- -- true -... -cn.space.net_box_test_space.index.primary:select(123) ---- -- - [123, 345] -... -cn.space.net_box_test_space.index.primary:select(123, { limit = 0 }) ---- -- [] -... -cn.space.net_box_test_space.index.primary:select(nil, { limit = 1, }) ---- -- - [123, 345] -... -cn.space.net_box_test_space:insert{234, 1,2,3} ---- -- [234, 1, 2, 3] -... -cn.space.net_box_test_space:insert{234, 1,2,3} ---- -- error: Duplicate key exists in unique index 'primary' in space 'net_box_test_space' -... -cn.space.net_box_test_space.insert{234, 1,2,3} ---- -- error: 'builtin/box/schema.lua..."]:: Use space:insert(...) instead of space.insert(...)' -... -cn.space.net_box_test_space:replace{354, 1,2,3} ---- -- [354, 1, 2, 3] -... -cn.space.net_box_test_space:replace{354, 1,2,4} ---- -- [354, 1, 2, 4] -... -cn.space.net_box_test_space:select{123} ---- -- - [123, 345] -... -space:select({123}, { iterator = 'GE' }) ---- -- - [123, 345] - - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn.space.net_box_test_space:select({123}, { iterator = 'GE' }) ---- -- - [123, 345] - - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn.space.net_box_test_space:select({123}, { iterator = 'GT' }) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1 }) ---- -- - [234, 1, 2, 3] -... -cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1, offset = 1 }) ---- -- - [354, 1, 2, 4] -... -cn.space.net_box_test_space:select{123} ---- -- - [123, 345] -... -cn.space.net_box_test_space:update({123}, { { '+', 2, 1 } }) ---- -- [123, 346] -... -cn.space.net_box_test_space:update(123, { { '+', 2, 1 } }) ---- -- [123, 347] -... -cn.space.net_box_test_space:select{123} ---- -- - [123, 347] -... -cn.space.net_box_test_space:insert(cn.space.net_box_test_space:get{123}:update{ { '=', 1, 2 } }) ---- -- [2, 347] -... -cn.space.net_box_test_space:delete{123} ---- -- [123, 347] -... -cn.space.net_box_test_space:select{2} ---- -- - [2, 347] -... -cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) ---- -- - [2, 347] -... -cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) ---- -... -cn.space.net_box_test_space:delete{1} ---- -... -cn.space.net_box_test_space:delete{2} ---- -- [2, 347] -... -cn.space.net_box_test_space:delete{2} ---- -... --- test one-based indexing in splice operation (see update.test.lua) -cn.space.net_box_test_space:replace({10, 'abcde'}) ---- -- [10, 'abcde'] -... -cn.space.net_box_test_space:update(10, {{':', 2, 0, 0, '!'}}) ---- -- error: 'SPLICE error on field 2: offset is out of bound' -... -cn.space.net_box_test_space:update(10, {{':', 2, 1, 0, '('}}) ---- -- [10, '(abcde'] -... -cn.space.net_box_test_space:update(10, {{':', 2, 2, 0, '({'}}) ---- -- [10, '(({abcde'] -... -cn.space.net_box_test_space:update(10, {{':', 2, -1, 0, ')'}}) ---- -- [10, '(({abcde)'] -... -cn.space.net_box_test_space:update(10, {{':', 2, -2, 0, '})'}}) ---- -- [10, '(({abcde}))'] -... -cn.space.net_box_test_space:delete{10} ---- -- [10, '(({abcde}))'] -... -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... --- gh-841: net.box uses incorrect iterator type for select with no arguments -cn.space.net_box_test_space:select() ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn.space.net_box_test_space.index.primary:min() ---- -- [234, 1, 2, 3] -... -cn.space.net_box_test_space.index.primary:min(354) ---- -- [354, 1, 2, 4] -... -cn.space.net_box_test_space.index.primary:max() ---- -- [354, 1, 2, 4] -... -cn.space.net_box_test_space.index.primary:max(234) ---- -- [234, 1, 2, 3] -... -cn.space.net_box_test_space.index.primary:count() ---- -- 2 -... -cn.space.net_box_test_space.index.primary:count(354) ---- -- 1 -... -cn.space.net_box_test_space:get(354) ---- -- [354, 1, 2, 4] -... --- reconnects after errors -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... -box.schema.func.create('test_foo') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'test_foo') ---- -... --- -- 1. no reconnect -x_fatal(cn) ---- -... -cn.state ---- -- error -... -cn:ping() ---- -- false -... -cn:call('test_foo') ---- -- error: Peer closed -... -cn:wait_state('active') ---- -- false -... --- -- 2 reconnect -cn = remote.connect(LISTEN.host, LISTEN.service, { reconnect_after = .1 }) ---- -... -cn.space ~= nil ---- -- true -... -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -x_fatal(cn) ---- -... -cn:wait_connected() ---- -- true -... -cn:wait_state('active') ---- -- true -... -cn:wait_state({active=true}) ---- -- true -... -cn:ping() ---- -- true -... -cn.state ---- -- active -... -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -x_fatal(cn) ---- -... -x_select(cn, space.id, 0, box.index.ALL, 0, 0xFFFFFFFF, {}) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn.state ---- -- active -... -cn:ping() ---- -- true -... --- -- dot-new-method -cn1 = remote.new(LISTEN.host, LISTEN.service) ---- -... -x_select(cn1, space.id, 0, box.index.ALL, 0, 0xFFFFFFF, {}) ---- -- - [234, 1, 2, 3] - - [354, 1, 2, 4] -... -cn1:close() ---- -... --- -- error while waiting for response -type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end)) ---- -- userdata -... -function pause() fiber.sleep(10) return true end ---- -... -box.schema.func.create('pause') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'pause') ---- -... -cn:call('pause') ---- -- error: Peer closed -... -cn:call('test_foo', {'a', 'b', 'c'}) ---- -- [[{'a': 1}], [{'b': 2}], 'c'] -... -box.schema.func.drop('pause') ---- -... --- call -remote.self:call('test_foo', {'a', 'b', 'c'}) ---- -- - - a: 1 - - - b: 2 - - c -... -cn:call('test_foo', {'a', 'b', 'c'}) ---- -- [[{'a': 1}], [{'b': 2}], 'c'] -... -box.schema.func.drop('test_foo') ---- -... -box.schema.func.create('long_rep') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'long_rep') ---- -... --- long replies -function long_rep() return { 1, string.rep('a', 5000) } end ---- -... -res = cn:call('long_rep') ---- -... -res[1] == 1 ---- -- true -... -res[2] == string.rep('a', 5000) ---- -- true -... -function long_rep() return { 1, string.rep('a', 50000) } end ---- -... -res = cn:call('long_rep') ---- -... -res[1] == 1 ---- -- true -... -res[2] == string.rep('a', 50000) ---- -- true -... -box.schema.func.drop('long_rep') ---- -... --- a.b.c.d -u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E' ---- -... -X = {} ---- -... -X.X = X ---- -... -function X.fn(x,y) return y or x end ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -cn:close() ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service) ---- -... -cn:call('X.fn', {u}) ---- -- 84F7BCFA-079C-46CC-98B4-F0C821BE833E -... -cn:call('X.X.X.X.X.X.X.fn', {u}) ---- -- 84F7BCFA-079C-46CC-98B4-F0C821BE833E -... -cn:call('X.X.X.X:fn', {u}) ---- -- 84F7BCFA-079C-46CC-98B4-F0C821BE833E -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... -cn:close() ---- -... --- auth -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123', wait_connected = true }) ---- -... -cn:is_connected() ---- -- false -... -cn.error ---- -- User 'netbox' is not found -... -cn.state ---- -- error -... -box.schema.user.create('netbox', { password = 'test' }) ---- -... -box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') ---- -... -box.schema.user.grant('netbox', 'execute', 'universe') ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' }) ---- -... -cn.state ---- -- active -... -cn.error ---- -- null -... -cn:ping() ---- -- true -... -function ret_after(to) fiber.sleep(to) return {{to}} end ---- -... -cn:ping({timeout = 1.00}) ---- -- true -... -cn:ping({timeout = 1e-9}) ---- -- false -... -cn:ping() ---- -- true -... -remote_space = cn.space.net_box_test_space ---- -... -remote_pk = remote_space.index.primary ---- -... -remote_space:insert({0}, { timeout = 1.00 }) ---- -- [0] -... -remote_space:insert({1}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_space:insert({2}) ---- -- [2] -... -remote_space:replace({0}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_space:replace({1}) ---- -- [1] -... -remote_space:replace({2}, { timeout = 1.00 }) ---- -- [2] -... -remote_space:upsert({3}, {}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_space:upsert({4}, {}) ---- -... -remote_space:upsert({5}, {}, { timeout = 1.00 }) ---- -... -remote_space:upsert({3}, {}) ---- -... -remote_space:update({3}, {}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_space:update({4}, {}) ---- -- [4] -... -remote_space:update({5}, {}, { timeout = 1.00 }) ---- -- [5] -... -remote_space:update({3}, {}) ---- -- [3] -... -remote_pk:update({5}, {}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:update({4}, {}) ---- -- [4] -... -remote_pk:update({3}, {}, { timeout = 1.00 }) ---- -- [3] -... -remote_pk:update({5}, {}) ---- -- [5] -... -remote_space:get({0}) ---- -- [0] -... -remote_space:get({1}, { timeout = 1.00 }) ---- -- [1] -... -remote_space:get({2}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:get({3}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:get({4}) ---- -- [4] -... -remote_pk:get({5}, { timeout = 1.00 }) ---- -- [5] -... -remote_space:select({2}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_space:select({2}, { timeout = 1.00 }) ---- -- - [2] -... -remote_space:select({2}) ---- -- - [2] -... -remote_pk:select({2}, { timeout = 1.00 }) ---- -- - [2] -... -remote_pk:select({2}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:select({2}) ---- -- - [2] -... -remote_space:select({5}, { timeout = 1.00, iterator = 'LE', limit = 5 }) ---- -- - [5] - - [4] - - [3] - - [2] - - [1] -... -remote_space:select({5}, { iterator = 'LE', limit = 5}) ---- -- - [5] - - [4] - - [3] - - [2] - - [1] -... -remote_space:select({5}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) ---- -- error: Timeout exceeded -... -remote_pk:select({2}, { timeout = 1.00, iterator = 'LE', limit = 5 }) ---- -- - [2] - - [1] - - [0] -... -remote_pk:select({2}, { iterator = 'LE', limit = 5}) ---- -- - [2] - - [1] - - [0] -... -remote_pk:select({2}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) ---- -- error: Timeout exceeded -... -remote_pk:count({2}, { timeout = 1.00}) ---- -- 1 -... -remote_pk:count({2}, { timeout = 1e-9}) ---- -- error: Timeout exceeded -... -remote_pk:count({2}) ---- -- 1 -... -remote_pk:count({2}, { timeout = 1.00, iterator = 'LE' }) ---- -- 3 -... -remote_pk:count({2}, { iterator = 'LE'}) ---- -- 3 -... -remote_pk:count({2}, { timeout = 1e-9, iterator = 'LE' }) ---- -- error: Timeout exceeded -... -remote_pk:min(nil, { timeout = 1.00 }) ---- -- [0] -... -remote_pk:min(nil, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:min(nil) ---- -- [0] -... -remote_pk:min({0}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:min({1}) ---- -- [1] -... -remote_pk:min({2}, { timeout = 1.00 }) ---- -- [2] -... -remote_pk:max(nil) ---- -- [354, 1, 2, 4] -... -remote_pk:max(nil, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:max(nil, { timeout = 1.00 }) ---- -- [354, 1, 2, 4] -... -remote_pk:max({0}, { timeout = 1.00 }) ---- -- [0] -... -remote_pk:max({1}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -remote_pk:max({2}) ---- -- [2] -... --- --- gh-3262: index:count() inconsistent results --- -test_run:cmd("setopt delimiter ';'") ---- -- true -... -function do_count_test(min, it) - local r1 = remote_pk:count(min, {iterator = it} ) - local r2 = box.space.net_box_test_space.index.primary:count(min, {iterator = it} ) - local r3 = remote.self.space.net_box_test_space.index.primary:count(min, {iterator = it} ) - return r1 == r2 and r2 == r3 -end; ---- -... -data = remote_pk:select(); ---- -... -for _, v in pairs(data) do - local itrs = {'GE', 'GT', 'LE', 'LT' } - for _, it in pairs(itrs) do - assert(do_count_test(v[0], it) == true) - end -end; ---- -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -_ = remote_space:delete({0}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -_ = remote_pk:delete({0}, { timeout = 1.00 }) ---- -... -_ = remote_space:delete({1}, { timeout = 1.00 }) ---- -... -_ = remote_pk:delete({1}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -_ = remote_space:delete({2}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -_ = remote_pk:delete({2}) ---- -... -_ = remote_pk:delete({3}) ---- -... -_ = remote_pk:delete({4}) ---- -... -_ = remote_pk:delete({5}) ---- -... -remote_space:get(0) ---- -... -remote_space:get(1) ---- -... -remote_space:get(2) ---- -... -remote_space = nil ---- -... -cn:call('ret_after', {0.01}, { timeout = 1.00 }) ---- -- [[0.01]] -... -cn:call('ret_after', {1.00}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... -cn:eval('return ret_after(...)', {0.01}, { timeout = 1.00 }) ---- -- [[0.01]] -... -cn:eval('return ret_after(...)', {1.00}, { timeout = 1e-9 }) ---- -- error: Timeout exceeded -... --- --- :timeout() --- @deprecated since 1.7.4 --- -cn:timeout(1).space.net_box_test_space.index.primary:select{234} ---- -- - [234, 1, 2, 3] -... -cn:call('ret_after', {.01}) ---- -- [[0.01]] -... -cn:timeout(1):call('ret_after', {.01}) ---- -- [[0.01]] -... -cn:timeout(.01):call('ret_after', {1}) ---- -- error: Timeout exceeded -... -cn = remote:timeout(0.0000000001):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) ---- -... -cn:close() ---- -... -cn = remote:timeout(1):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) ---- -... -remote.self:ping() ---- -- true -... -remote.self.space.net_box_test_space:select{234} ---- -- - [234, 1, 2, 3] -... -remote.self:timeout(123).space.net_box_test_space:select{234} ---- -- - [234, 1, 2, 3] -... -remote.self:is_connected() ---- -- true -... -remote.self:wait_connected() ---- -- true -... -cn:close() ---- -... --- cleanup database after tests -space:drop() ---- -... --- #1545 empty password -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'test' }) ---- -... -cn ~= nil ---- -- true -... -cn:close() ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service, { password = 'test' }) ---- -- error: 'net.box: user is not defined' -... -cn ~= nil ---- -- true -... -cn:close() ---- -... --- #544 usage for remote[point]method -cn = remote.connect(LISTEN.host, LISTEN.service) ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -cn:close() ---- -... -cn = remote.connect(LISTEN.host, LISTEN.service) ---- -... -cn:eval('return true') ---- -- true -... -cn.eval('return true') ---- -- error: 'Use remote:eval(...) instead of remote.eval(...):' -... -cn.ping() ---- -- error: 'Use remote:ping(...) instead of remote.ping(...):' -... -cn:close() ---- -... -remote.self:eval('return true') ---- -- true -... -remote.self.eval('return true') ---- -- error: 'Use remote:eval(...) instead of remote.eval(...):' -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- uri as the first argument -uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service) ---- -... -cn = remote.new(uri) ---- -... -cn:ping() ---- -- true -... -cn:close() ---- -... -uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) ---- -... -cn = remote.new(uri) ---- -... -cn ~= nil, cn.state, cn.error ---- -- true -- error -- Incorrect password supplied for user 'netbox' -... -cn:close() ---- -... --- don't merge creds from uri & opts -remote.new(uri, { password = 'test' }) ---- -- error: 'net.box: user is not defined' -... -cn = remote.new(uri, { user = 'netbox', password = 'test' }) ---- -... -cn:ping() ---- -- true -... -cn:close() ---- -... -box.schema.user.drop('netbox') ---- -... --- #594: bad argument #1 to 'setmetatable' (table expected, got number) -box.schema.func.create('dostring') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'dostring') ---- -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... -function gh594() - local cn = remote.connect(box.cfg.listen) - local ping = fiber.create(function() cn:ping() end) - cn:call('dostring', {'return 2 + 2'}) - cn:close() -end; ---- -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -gh594() ---- -... -box.schema.func.drop('dostring') ---- -... --- #636: Reload schema on demand -sp = box.schema.space.create('test_old') ---- -... -_ = sp:create_index('primary') ---- -... -sp:insert{1, 2, 3} ---- -- [1, 2, 3] -... -box.schema.user.grant('guest', 'read', 'space', 'test_old') ---- -... -con = remote.new(box.cfg.listen) ---- -... -con:ping() ---- -- true -... -con.space.test_old:select{} ---- -- - [1, 2, 3] -... -con.space.test == nil ---- -- true -... -sp = box.schema.space.create('test') ---- -... -_ = sp:create_index('primary') ---- -... -sp:insert{2, 3, 4} ---- -- [2, 3, 4] -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -con.space.test == nil ---- -- true -... -con:reload_schema() ---- -... -con.space.test:select{} ---- -- - [2, 3, 4] -... -box.space.test:drop() ---- -... -box.space.test_old:drop() ---- -... -con:close() ---- -... -name = string.match(arg[0], "([^,]+)%.lua") ---- -... -file_log = require('fio').open(name .. '.log', {'O_RDONLY', 'O_NONBLOCK'}) ---- -... -file_log:seek(0, 'SEEK_END') ~= 0 ---- -- true -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... -_ = fiber.create( - function() - local conn = require('net.box').new(box.cfg.listen) - conn:call('no_such_function', {}) - conn:close() - end -); ---- -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -test_run:wait_log('default', 'ER_NO_SUCH_PROC', nil, 10) ---- -- ER_NO_SUCH_PROC -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- --- gh-3900: tarantool can be crashed by sending gibberish to a --- binary socket --- -socket = require("socket") ---- -... -sock = socket.tcp_connect(LISTEN.host, LISTEN.service) ---- -... -data = string.fromhex("6783000000000000000000000000000000000000000000800000C8000000000000000000000000000000000000000000FFFF210100373208000000FFFF000055AAEB66486472530D02000000000010A0350001008000001000000000000000000000000000D05700") ---- -... -sock:write(data) ---- -- 104 -... -test_run:wait_log('default', 'ER_INVALID_MSGPACK: Invalid MsgPack %- packet body', nil, 10) ---- -- 'ER_INVALID_MSGPACK: Invalid MsgPack - packet body' -... -sock:close() ---- -- true -... --- gh-983 selecting a lot of data crashes the server or hangs the --- connection --- gh-983 test case: iproto connection selecting a lot of data -_ = box.schema.space.create('test', { temporary = true }) ---- -... -_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) ---- -... -data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhh" ---- -... -for i = 0,10000 do box.space.test:insert{i, data1k} end ---- -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -net = require('net.box') ---- -... -c = net:connect(box.cfg.listen) ---- -... -r = c.space.test:select(nil, {limit=5000}) ---- -... -box.space.test:drop() ---- -... --- gh-970 gh-971 UPSERT over network -_ = box.schema.space.create('test') ---- -... -_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) ---- -... -_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) ---- -... -_ = box.space.test:insert{1, 2, "string"} ---- -... -box.schema.user.grant('guest', 'read,write', 'space', 'test') ---- -... -c = net:connect(box.cfg.listen) ---- -... -c.space.test:select{} ---- -- - [1, 2, 'string'] -... -c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update ---- -... -c.space.test:select{} ---- -- - [1, 3, 'string'] -... -c.space.test:upsert({2, 4, 'something'}, {{'+', 2, 1}}) -- insert ---- -... -c.space.test:select{} ---- -- - [1, 3, 'string'] - - [2, 4, 'something'] -... -c.space.test:upsert({2, 4, 'nothing'}, {{'+', 3, 100500}}) -- wrong operation ---- -... -c.space.test:select{} ---- -- - [1, 3, 'string'] - - [2, 4, 'something'] -... --- gh-1729 net.box index metadata incompatible with local metadata -c.space.test.index.primary.parts ---- -- - type: unsigned - is_nullable: false - fieldno: 1 -... -c.space.test.index.covering.parts ---- -- - type: unsigned - is_nullable: false - fieldno: 1 - - type: string - is_nullable: false - fieldno: 3 - - type: unsigned - is_nullable: false - fieldno: 2 -... -box.space.test:drop() ---- -... --- CALL vs CALL_16 in connect options -function echo(...) return ... end ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:call('echo', {42}) ---- -- 42 -... -c:eval('return echo(...)', {42}) ---- -- 42 -... --- invalid arguments -c:call('echo', 42) ---- -- error: 'builtin/box/net_box.lua..."]:: Use remote:call(func_name, {arg1, arg2, ...}, - opts) instead of remote:call(func_name, arg1, arg2, ...)' -... -c:eval('return echo(...)', 42) ---- -- error: 'builtin/box/net_box.lua..."]:: Use remote:eval(expression, {arg1, arg2, ...}, - opts) instead of remote:eval(expression, arg1, arg2, ...)' -... -c:close() ---- -... -c = net.connect(box.cfg.listen, {call_16 = true}) ---- -... -c:call('echo', 42) ---- -- - [42] -... -c:eval('return echo(...)', 42) ---- -- 42 -... -c:close() ---- -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- --- gh-2195 export pure msgpack from net.box --- -space = box.schema.space.create('test') ---- -... -_ = box.space.test:create_index('primary') ---- -... -box.schema.user.grant('guest', 'read,write', 'space', 'test') ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -c = net.connect(box.cfg.listen) ---- -... -ibuf = require('buffer').ibuf() ---- -... -c:ping() ---- -- true -... -c.space.test ~= nil ---- -- true -... -c.space.test:replace({1, 'hello'}) ---- -- [1, 'hello'] -... --- replace -c.space.test:replace({2}, {buffer = ibuf}) ---- -- 9 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [[2]]} -... --- replace + skip_header -c.space.test:replace({2}, {buffer = ibuf, skip_header = true}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [[2]] -... --- insert -c.space.test:insert({3}, {buffer = ibuf}) ---- -- 9 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [[3]]} -... --- insert + skip_header -_ = space:delete({3}) ---- -... -c.space.test:insert({3}, {buffer = ibuf, skip_header = true}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [[3]] -... --- update -c.space.test:update({3}, {}, {buffer = ibuf}) ---- -- 9 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [[3]]} -... -c.space.test.index.primary:update({3}, {}, {buffer = ibuf}) ---- -- 9 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [[3]]} -... --- update + skip_header -c.space.test:update({3}, {}, {buffer = ibuf, skip_header = true}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [[3]] -... -c.space.test.index.primary:update({3}, {}, {buffer = ibuf, skip_header = true}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [[3]] -... --- upsert -c.space.test:upsert({4}, {}, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... --- upsert + skip_header -c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... --- delete -c.space.test:upsert({4}, {}, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... --- delete + skip_header -c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... --- select -c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf}) ---- -- 19 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [[3], [2], [1, 'hello']]} -... --- select + skip_header -c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf, skip_header = true}) ---- -- 17 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [[3], [2], [1, 'hello']] -... --- select -len = c.space.test:select({}, {buffer = ibuf}) ---- -... -ibuf.rpos + len == ibuf.wpos ---- -- true -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -ibuf.rpos == ibuf.wpos ---- -- true -... -len ---- -- 21 -... -result ---- -- {48: [[1, 'hello'], [2], [3], [4]]} -... --- select + skip_header -len = c.space.test:select({}, {buffer = ibuf, skip_header = true}) ---- -... -ibuf.rpos + len == ibuf.wpos ---- -- true -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -ibuf.rpos == ibuf.wpos ---- -- true -... -len ---- -- 19 -... -result ---- -- [[1, 'hello'], [2], [3], [4]] -... --- call -c:call("echo", {1, 2, 3}, {buffer = ibuf}) ---- -- 10 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [1, 2, 3]} -... -c:call("echo", {}, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... -c:call("echo", nil, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... --- call + skip_header -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) ---- -- 8 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [1, 2, 3] -... -c:call("echo", {}, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... -c:call("echo", nil, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... --- eval -c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... -c:eval("echo(...)", {}, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... -c:eval("echo(...)", nil, {buffer = ibuf}) ---- -- 7 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: []} -... --- eval + skip_header -c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... -c:eval("echo(...)", {}, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... -c:eval("echo(...)", nil, {buffer = ibuf, skip_header = true}) ---- -- 5 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [] -... --- make several request into a buffer with skip_header, then read --- results -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) ---- -- 8 -... -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) ---- -- 8 -... -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) ---- -- 8 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [1, 2, 3] -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [1, 2, 3] -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- [1, 2, 3] -... --- unsupported methods -c.space.test:get({1}, { buffer = ibuf}) ---- -- error: 'builtin/box/net_box.lua..."]:: index:get() doesn''t support `buffer` argument' -... -c.space.test.index.primary:min({}, { buffer = ibuf}) ---- -- error: 'builtin/box/net_box.lua..."]:: index:min() doesn''t support `buffer` argument' -... -c.space.test.index.primary:max({}, { buffer = ibuf}) ---- -- error: 'builtin/box/net_box.lua..."]:: index:max() doesn''t support `buffer` argument' -... -c.space.test.index.primary:count({}, { buffer = ibuf}) ---- -- error: 'builtin/box/net_box.lua..."]:: index:count() doesn''t support `buffer` argument' -... -c.space.test.index.primary:get({1}, { buffer = ibuf}) ---- -- error: 'builtin/box/net_box.lua..."]:: index:get() doesn''t support `buffer` argument' -... --- error handling -rpos, wpos = ibuf.rpos, ibuf.wpos ---- -... -c.space.test:insert({1}, {buffer = ibuf}) ---- -- error: Duplicate key exists in unique index 'primary' in space 'test' -... -ibuf.rpos == rpos, ibuf.wpos == wpos ---- -- true -- true -... -ibuf = nil ---- -... -c:close() ---- -... -space:drop() ---- -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- gh-1904 net.box hangs in :close() if a fiber was cancelled --- while blocked in :_wait_state() in :_request() -options = {user = 'netbox', password = 'badpass', wait_connected = false, reconnect_after = 0.01} ---- -... -c = net:new(box.cfg.listen, options) ---- -... -f = fiber.create(function() c:call("") end) ---- -... -fiber.sleep(0.01) ---- -... -f:cancel(); c:close() ---- -... -box.schema.user.grant('guest', 'read', 'space', '_schema') ---- -... --- check for on_schema_reload callback -test_run:cmd("setopt delimiter ';'") ---- -- true -... -do - local a = 0 - function osr_cb() - a = a + 1 - end - local con = net.new(box.cfg.listen, { - wait_connected = false - }) - con:on_schema_reload(osr_cb) - con:wait_connected() - con.space._schema:select{} - box.schema.space.create('misisipi') - box.space.misisipi:drop() - con.space._schema:select{} - con:close() - con = nil - - return a -end; ---- -- 2 -... -do - local a = 0 - function osr_cb() - a = a + 1 - end - local con = net.new(box.cfg.listen, { - wait_connected = true - }) - con:on_schema_reload(osr_cb) - con.space._schema:select{} - box.schema.space.create('misisipi') - box.space.misisipi:drop() - con.space._schema:select{} - con:close() - con = nil - - return a -end; ---- -- 1 -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -box.schema.user.revoke('guest', 'read', 'space', '_schema') ---- -... --- Tarantool < 1.7.1 compatibility (gh-1533) -c = net.new(box.cfg.listen) ---- -... -c:ping() ---- -- true -... -c:close() ---- -... --- Test for connect_timeout > 0 in netbox connect -test_run:cmd("setopt delimiter ';'"); ---- -- true -... -need_stop = false; ---- -... -greeting = -"Tarantool 1.7.3 (Lua console)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" .. -"type 'help' for interactive help~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; ---- -... -socket = require('socket'); ---- -... -srv = socket.tcp_server('localhost', 0, { - handler = function(fd) - local fiber = require('fiber') - while not need_stop do - fiber.sleep(0.01) - end - fd:write(greeting) - end -}); ---- -... --- we must get timeout -port = srv:name().port -nb = net.new('localhost:' .. port, { - wait_connected = true, console = true, - connect_timeout = 0.1 -}); ---- -... -nb.error:find('timed out') ~= nil; ---- -- true -... -need_stop = true -nb:close(); ---- -... --- we must get peer closed -nb = net.new('localhost:' .. port, { - wait_connected = true, console = true, - connect_timeout = 0.2 -}); ---- -... -nb.error ~= "Timeout exceeded"; ---- -- true -... -nb:close(); ---- -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -srv:close() ---- -- true -... -test_run:cmd("clear filter") ---- -- true -... --- --- gh-2402 net.box doesn't support space:format() --- -space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) ---- -... -space ~= nil ---- -- true -... -_ = box.space.test:create_index('primary') ---- -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:ping() ---- -- true -... -c.space.test ~= nil ---- -- true -... -format = c.space.test:format() ---- -... -format[1] ~= nil ---- -- true -... -format[1].name == "id" ---- -- true -... -format[1].type == "unsigned" ---- -- true -... -c.space.test:format({}) ---- -- error: net.box does not support setting space format -... --- --- gh-4091: index unique flag is always false. --- -c.space.test.index.primary.unique ---- -- true -... -c:close() ---- -... -space:drop() ---- -... --- --- Check that it's possible to get connection object form net.box space --- -space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) ---- -... -space ~= nil ---- -- true -... -_ = box.space.test:create_index('primary') ---- -... -box.schema.user.grant('guest','read,write,execute','space', 'test') ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:ping() ---- -- true -... -c.space.test ~= nil ---- -- true -... -c.space.test.connection == c ---- -- true -... -box.schema.user.revoke('guest','read,write,execute','space', 'test') ---- -... -c:close() ---- -... --- --- gh-2642: box.session.type() --- -box.schema.user.grant('guest','execute','universe') ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:call("box.session.type") ---- -- binary -... -c:close() ---- -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... --- --- On_connect/disconnect triggers. --- -test_run:cmd('create server connecter with script = "box/proxy.lua"') ---- -- true -... -test_run:cmd('start server connecter') ---- -- true -... -test_run:cmd("set variable connect_to to 'connecter.listen'") ---- -- true -... -conn = net.connect(connect_to, { reconnect_after = 0.1 }) ---- -... -conn.state ---- -- active -... -connected_cnt = 0 ---- -... -disconnected_cnt = 0 ---- -... -function on_connect() connected_cnt = connected_cnt + 1 end ---- -... -function on_disconnect() disconnected_cnt = disconnected_cnt + 1 end ---- -... -conn:on_connect(on_connect) ---- -... -conn:on_disconnect(on_disconnect) ---- -... -test_run:cmd('stop server connecter') ---- -- true -... -test_run:cmd('start server connecter') ---- -- true -... -while conn.state ~= 'active' do fiber.sleep(0.1) end ---- -... -connected_cnt ---- -- 1 -... -old_disconnected_cnt = disconnected_cnt ---- -... -disconnected_cnt >= 1 ---- -- true -... -conn:close() ---- -... -disconnected_cnt == old_disconnected_cnt + 1 ---- -- true -... -test_run:cmd('stop server connecter') ---- -- true -... --- --- gh-2401 update pseudo objects not replace them --- -space:drop() ---- -... -space = box.schema.space.create('test') ---- -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -c = net.connect(box.cfg.listen) ---- -... -cspace = c.space.test ---- -... -space.index.test_index == nil ---- -- true -... -cspace.index.test_index == nil ---- -- true -... -_ = space:create_index("test_index", {parts={1, 'string'}}) ---- -... -c:reload_schema() ---- -... -space.index.test_index ~= nil ---- -- true -... -cspace.index.test_index ~= nil ---- -- true -... -c.space.test.index.test_index ~= nil ---- -- true -... --- cleanup -space:drop() ---- -... --- --- gh-946: long polling CALL blocks input --- -box.schema.func.create('fast_call') ---- -... -box.schema.func.create('long_call') ---- -... -box.schema.func.create('wait_signal') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'fast_call') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'long_call') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') ---- -... -c = net.connect(box.cfg.listen) ---- -... -N = 100 ---- -... -pad = string.rep('x', 1024) ---- -... -long_call_cond = fiber.cond() ---- -... -long_call_channel = fiber.channel() ---- -... -fast_call_channel = fiber.channel() ---- -... -function fast_call(x) return x end ---- -... -function long_call(x) long_call_cond:wait() return x * 2 end ---- -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... -for i = 1, N do - fiber.create(function() - fast_call_channel:put(c:call('fast_call', {i, pad})) - end) - fiber.create(function() - long_call_channel:put(c:call('long_call', {i, pad})) - end) -end -test_run:cmd("setopt delimiter ''"); ---- -... -x = 0 ---- -... -for i = 1, N do x = x + fast_call_channel:get() end ---- -... -x ---- -- 5050 -... -long_call_cond:broadcast() ---- -... -x = 0 ---- -... -for i = 1, N do x = x + long_call_channel:get() end ---- -... -x ---- -- 10100 -... --- --- Check that a connection does not leak if there is --- a long CALL in progress when it is closed. --- -disconnected = false ---- -... -function on_disconnect() disconnected = true end ---- -... --- Make sure all dangling connections are collected so --- that on_disconnect trigger isn't called spuriously. -collectgarbage('collect') ---- -- 0 -... -fiber.sleep(0) ---- -... -box.session.on_disconnect(on_disconnect) == on_disconnect ---- -- true -... --- --- gh-3859: on_disconnect is called only after all requests are --- processed, but should be called right after disconnect and --- only once. --- -ch1 = fiber.channel(1) ---- -... -ch2 = fiber.channel(1) ---- -... -function wait_signal() ch1:put(true) ch2:get() end ---- -... -_ = fiber.create(function() c:call('wait_signal') end) ---- -... -ch1:get() ---- -- true -... -c:close() ---- -... -fiber.sleep(0) ---- -... -while disconnected == false do fiber.sleep(0.01) end ---- -... -disconnected -- true ---- -- true -... -disconnected = nil ---- -... -ch2:put(true) ---- -- true -... -fiber.sleep(0) ---- -... -disconnected -- nil, on_disconnect is not called second time. ---- -- null -... -box.session.on_disconnect(nil, on_disconnect) ---- -... -box.schema.func.drop('long_call') ---- -... -box.schema.func.drop('fast_call') ---- -... -box.schema.func.drop('wait_signal') ---- -... --- --- gh-2666: check that netbox.call is not repeated on schema --- change. --- -box.schema.user.grant('guest', 'write', 'space', '_space') ---- -... -box.schema.user.grant('guest', 'write', 'space', '_schema') ---- -... -box.schema.user.grant('guest', 'create', 'universe') ---- -... -count = 0 ---- -... -function create_space(name) count = count + 1 box.schema.create_space(name) return true end ---- -... -box.schema.func.create('create_space') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'create_space') ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:call('create_space', {'test1'}) ---- -- true -... -count ---- -- 1 -... -c:call('create_space', {'test2'}) ---- -- true -... -count ---- -- 2 -... -c:call('create_space', {'test3'}) ---- -- true -... -count ---- -- 3 -... -box.space.test1:drop() ---- -... -box.space.test2:drop() ---- -... -box.space.test3:drop() ---- -... -box.schema.user.revoke('guest', 'write', 'space', '_space') ---- -... -box.schema.user.revoke('guest', 'write', 'space', '_schema') ---- -... -box.schema.user.revoke('guest', 'create', 'universe') ---- -... -c:close() ---- -... -box.schema.func.drop('create_space') ---- -... --- --- gh-3164: netbox connection is not closed and garbage collected --- ever, if reconnect_after is set. --- -test_run:cmd('start server connecter') ---- -- true -... -test_run:cmd("set variable connect_to to 'connecter.listen'") ---- -- true -... -weak = setmetatable({}, {__mode = 'v'}) ---- -... --- Create strong and weak reference. Weak is valid until strong --- is valid too. -strong = net.connect(connect_to, {reconnect_after = 0.1}) ---- -... -weak.c = strong ---- -... -weak.c:ping() ---- -- true -... -test_run:cmd('stop server connecter') ---- -- true -... -test_run:cmd('cleanup server connecter') ---- -- true -... --- Check the connection tries to reconnect at least two times. --- 'Cannot assign requested address' is the crutch for running the --- tests in a docker. This error emits instead of --- 'Connection refused' inside a docker. -old_log_level = box.cfg.log_level ---- -... -box.cfg{log_level = 6} ---- -... -log.info(string.rep('a', 1000)) ---- -... -test_run:cmd("setopt delimiter ';'") ---- -- true -... -while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and - test_run:grep_log('default', 'Connection refused', 1000) == nil and - test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do - fiber.sleep(0.1) -end; ---- -... -log.info(string.rep('a', 1000)); ---- -... -while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and - test_run:grep_log('default', 'Connection refused', 1000) == nil and - test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do - fiber.sleep(0.1) -end; ---- -... -test_run:cmd("setopt delimiter ''"); ---- -- true -... -box.cfg{log_level = old_log_level} ---- -... -collectgarbage('collect') ---- -- 0 -... -strong.state ---- -- error_reconnect -... -strong == weak.c ---- -- true -... --- Remove single strong reference. Now connection must be garbage --- collected. -strong = nil ---- -... -collectgarbage('collect') ---- -- 0 -... --- Now weak.c is null, because it was weak reference, and the --- connection is deleted by 'collect'. -weak.c ---- -- null -... --- --- gh-2677: netbox supports console connections, that complicates --- both console and netbox. It was necessary because before a --- connection is established, a console does not known is it --- binary or text protocol, and netbox could not be created from --- existing socket. --- -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -urilib = require('uri') ---- -... -uri = urilib.parse(tostring(box.cfg.listen)) ---- -... -s, greeting = net.establish_connection(uri.host, uri.service) ---- -... -c = net.wrap(s, greeting, uri.host, uri.service, {reconnect_after = 0.01}) ---- -... -c.state ---- -- active -... -a = 100 ---- -... -function kek(args) return {1, 2, 3, args} end ---- -... -c:eval('a = 200') ---- -... -a ---- -- 200 -... -c:call('kek', {300}) ---- -- [1, 2, 3, 300] -... -s = box.schema.create_space('test') ---- -... -box.schema.user.grant('guest', 'read,write', 'space', 'test') ---- -... -pk = s:create_index('pk') ---- -... -c:reload_schema() ---- -... -c.space.test:replace{1} ---- -- [1] -... -c.space.test:get{1} ---- -- [1] -... -c.space.test:delete{1} ---- -- [1] -... --- --- Break a connection to test reconnect_after. --- -_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') ---- -... -while not c:is_connected() do fiber.sleep(0.01) end ---- -... -c:ping() ---- -- true -... -s:drop() ---- -... -c:close() ---- -... --- --- Test a case, when netbox can not connect first time, but --- reconnect_after is set. --- -c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false}) ---- -... -while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end ---- -... -c:close() ---- -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... -c.state ---- -- closed -... -c = nil ---- -... --- --- gh-3256 net.box is_nullable and collation options output --- -space = box.schema.create_space('test') ---- -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -_ = space:create_index('pk') ---- -... -_ = space:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}}) ---- -... -c = net:connect(box.cfg.listen) ---- -... -c.space.test.index.sk.parts ---- -- - type: unsigned - is_nullable: true - fieldno: 2 -... -space:drop() ---- -... -space = box.schema.create_space('test') ---- -... -c:close() ---- -... -box.schema.user.grant('guest', 'read', 'space', 'test') ---- -... -c = net:connect(box.cfg.listen) ---- -... -box.internal.collation.create('test', 'ICU', 'ru-RU') ---- -... -collation_id = box.internal.collation.id_by_name('test') ---- -... -_ = space:create_index('sk', { type = 'tree', parts = {{1, 'str', collation = 'test'}}, unique = true }) ---- -... -c:reload_schema() ---- -... -parts = c.space.test.index.sk.parts ---- -... -#parts == 1 ---- -- true -... -parts[1].fieldno == 1 ---- -- true -... -parts[1].type == 'string' ---- -- true -... -parts[1].is_nullable == false ---- -- true -... -if _TARANTOOL >= '2.2.1' then \ - return parts[1].collation == 'test' \ -else \ - return parts[1].collation_id == collation_id \ -end ---- -- true -... -c:close() ---- -... -box.internal.collation.drop('test') ---- -... -space:drop() ---- -... -c.state ---- -- closed -... -c = nil ---- -... --- --- gh-3107: fiber-async netbox. --- -cond = nil ---- -... -box.schema.func.create('long_function') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'long_function') ---- -... -function long_function(...) cond = fiber.cond() cond:wait() return ... end ---- -... -function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end ---- -... -s = box.schema.create_space('test') ---- -... -pk = s:create_index('pk') ---- -... -s:replace{1} ---- -- [1] -... -s:replace{2} ---- -- [2] -... -s:replace{3} ---- -- [3] -... -s:replace{4} ---- -- [4] -... -c = net:connect(box.cfg.listen) ---- -... --- --- Check long connections, multiple wait_result(). --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -future:result() ---- -- null -- Response is not ready -... -future:is_ready() ---- -- false -... -future:wait_result(0.01) -- Must fail on timeout. ---- -- null -- Timeout exceeded -... -finalize_long() ---- -... -ret = future:wait_result(100) ---- -... -future:is_ready() ---- -- true -... --- Any timeout is ok - response is received already. -future:wait_result(0) ---- -- [1, 2, 3] -... -future:wait_result(0.01) ---- -- [1, 2, 3] -... -ret ---- -- [1, 2, 3] -... -_, err = pcall(future.wait_result, future, true) ---- -... -err:find('Usage') ~= nil ---- -- true -... -_, err = pcall(future.wait_result, future, '100') ---- -... -err:find('Usage') ~= nil ---- -- true -... --- --- Check infinity timeout. --- -ret = nil ---- -... -_ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async = true}):wait_result() end) ---- -... -finalize_long() ---- -... -while not ret do fiber.sleep(0.01) end ---- -... -ret ---- -- [1, 2, 3] -... -c:close() ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -c = net:connect(box.cfg.listen) ---- -... -future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true}) ---- -... -future:result() ---- -- null -- Response is not ready -... -future:wait_result(0.01) -- Must fail on timeout. ---- -- null -- Timeout exceeded -... -finalize_long() ---- -... -future:wait_result(100) ---- -- [1, 2, 3] -... -c:close() ---- -... --- --- Check that is_async does not work on a closed connection. --- -c:call('any_func', {}, {is_async = true}) ---- -- error: Connection closed -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... -c = net:connect(box.cfg.listen) ---- -... --- --- Ensure the request is garbage collected both if is not used and --- if is. --- -gc_test = setmetatable({}, {__mode = 'v'}) ---- -... -gc_test.future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -gc_test.future ~= nil ---- -- true -... -collectgarbage() ---- -- 0 -... -gc_test ---- -- [] -... -finalize_long() ---- -... -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -collectgarbage() ---- -- 0 -... -future ~= nil ---- -- true -... -finalize_long() ---- -... -future:wait_result(1000) ---- -- [1, 2, 3] -... -collectgarbage() ---- -- 0 -... -future ~= nil ---- -- true -... -gc_test.future = future ---- -... -future = nil ---- -... -collectgarbage() ---- -- 0 -... -gc_test ---- -- [] -... --- --- Ensure a request can be finalized from non-caller fibers. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -ret = {} ---- -... -count = 0 ---- -... -for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end ---- -... -future:wait_result(0.01) -- Must fail on timeout. ---- -- null -- Timeout exceeded -... -finalize_long() ---- -... -while count ~= 10 do fiber.sleep(0.1) end ---- -... -ret ---- -- - &0 [1, 2, 3] - - *0 - - *0 - - *0 - - *0 - - *0 - - *0 - - *0 - - *0 - - *0 -... --- --- Test space methods. --- -c:close() ---- -... -box.schema.user.grant('guest', 'read,write', 'space', 'test') ---- -... -c = net:connect(box.cfg.listen) ---- -... -future = c.space.test:select({1}, {is_async = true}) ---- -... -ret = future:wait_result(100) ---- -... -ret ---- -- - [1] -... -type(ret[1]) ---- -- cdata -... -future = c.space.test:insert({5}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [5] -... -s:get{5} ---- -- [5] -... -future = c.space.test:replace({6}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [6] -... -s:get{6} ---- -- [6] -... -future = c.space.test:delete({6}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [6] -... -s:get{6} ---- -... -future = c.space.test:update({5}, {{'=', 2, 5}}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [5, 5] -... -s:get{5} ---- -- [5, 5] -... -future = c.space.test:upsert({5}, {{'=', 2, 6}}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- null -... -s:get{5} ---- -- [5, 6] -... -future = c.space.test:get({5}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [5, 6] -... --- --- Test index methods. --- -future = c.space.test.index.pk:select({1}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- - [1] -... -future = c.space.test.index.pk:get({2}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [2] -... -future = c.space.test.index.pk:min({}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [1] -... -future = c.space.test.index.pk:max({}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [5, 6] -... -c:close() ---- -... -box.schema.user.grant('guest', 'execute', 'universe') ---- -... -c = net:connect(box.cfg.listen) ---- -... -future = c.space.test.index.pk:count({3}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- 1 -... -c:close() ---- -... -box.schema.user.revoke('guest', 'execute', 'universe') ---- -... -c = net:connect(box.cfg.listen) ---- -... -future = c.space.test.index.pk:delete({3}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [3] -... -s:get{3} ---- -... -future = c.space.test.index.pk:update({4}, {{'=', 2, 6}}, {is_async = true}) ---- -... -future:wait_result(100) ---- -- [4, 6] -... -s:get{4} ---- -- [4, 6] -... --- --- Test async errors. --- -future = c.space.test:insert({1}, {is_async = true}) ---- -... -future:wait_result() ---- -- null -- Duplicate key exists in unique index 'pk' in space 'test' -... -future:result() ---- -- null -- Duplicate key exists in unique index 'pk' in space 'test' -... --- --- Test discard. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -future:discard() ---- -... -finalize_long() ---- -... -future:result() ---- -- null -- Response is discarded -... -future:wait_result(100) ---- -- null -- Response is discarded -... --- --- Test closed connection. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -finalize_long() ---- -... -future:wait_result(100) ---- -- [1, 2, 3] -... -future2 = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -c:close() ---- -... -future2:wait_result(100) ---- -- null -- Connection closed -... -future2:result() ---- -- null -- Connection closed -... -future2:discard() ---- -... --- Already successful result must be available. -future:wait_result(100) ---- -- [1, 2, 3] -... -future:result() ---- -- [1, 2, 3] -... -future:is_ready() ---- -- true -... -finalize_long() ---- -... --- --- Test reconnect. --- -c = net:connect(box.cfg.listen, {reconnect_after = 0.01}) ---- -... -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') ---- -... -while not c:is_connected() do fiber.sleep(0.01) end ---- -... -finalize_long() ---- -... -future:wait_result(100) ---- -- null -- Peer closed -... -future:result() ---- -- null -- Peer closed -... -future = c:call('long_function', {1, 2, 3}, {is_async = true}) ---- -... -finalize_long() ---- -... -future:wait_result(100) ---- -- [1, 2, 3] -... --- --- Test raw response getting. --- -ibuf = require('buffer').ibuf() ---- -... -future = c:call('long_function', {1, 2, 3}, {is_async = true, buffer = ibuf}) ---- -... -finalize_long() ---- -... -future:wait_result(100) ---- -- 10 -... -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) ---- -... -result ---- -- {48: [1, 2, 3]} -... -box.schema.func.drop('long_function') ---- -... --- --- Test async schema version change. --- -function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end ---- -... -box.schema.func.create('change_schema') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'change_schema') ---- -... -box.schema.user.grant('guest', 'write', 'space', '_schema') ---- -... -box.schema.user.grant('guest', 'read,write', 'space', '_space') ---- -... -box.schema.user.grant('guest', 'create', 'space') ---- -... -future1 = c:call('change_schema', {'1'}, {is_async = true}) ---- -... -future2 = c:call('change_schema', {'2'}, {is_async = true}) ---- -... -future3 = c:call('change_schema', {'3'}, {is_async = true}) ---- -... -future1:wait_result() ---- -- ['ok'] -... -future2:wait_result() ---- -- ['ok'] -... -future3:wait_result() ---- -- ['ok'] -... -c:close() ---- -... -s:drop() ---- -... -box.space.test1:drop() ---- -... -box.space.test2:drop() ---- -... -box.space.test3:drop() ---- -... -box.schema.func.drop('change_schema') ---- -... --- --- gh-2978: field names for tuples received from netbox. --- -_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}}) ---- -... -_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}}) ---- -... -box.space.named:insert({1, 1}) ---- -- [1, 1] -... -box.schema.user.grant('guest', 'read, write, execute', 'space') ---- -... -cn = net.connect(box.cfg.listen) ---- -... -s = cn.space.named ---- -... -s:get{1}.id ---- -- 1 -... -s:get{1}:tomap() ---- -- 1: 1 - 2: 1 - abc: 1 - id: 1 -... -s:insert{2,3}:tomap() ---- -- 1: 2 - 2: 3 - abc: 3 - id: 2 -... -s:replace{2,14}:tomap() ---- -- 1: 2 - 2: 14 - abc: 14 - id: 2 -... -s:update(1, {{'+', 2, 10}}):tomap() ---- -- 1: 1 - 2: 11 - abc: 11 - id: 1 -... -s:select()[1]:tomap() ---- -- 1: 1 - 2: 11 - abc: 11 - id: 1 -... -s:delete({2}):tomap() ---- -- 1: 2 - 2: 14 - abc: 14 - id: 2 -... --- Check that formats changes after reload. -box.space.named:format({{name = "id2"}, {name="abc2"}}) ---- -... -s:select()[1]:tomap() ---- -- 1: 1 - 2: 11 - abc: 11 - id: 1 -... -cn:reload_schema() ---- -... -s:select()[1]:tomap() ---- -- 1: 1 - 2: 11 - id2: 1 - abc2: 11 -... -cn:close() ---- -... -box.space.named:drop() ---- -... -box.schema.user.revoke('guest', 'read, write, execute', 'space') ---- -... --- --- gh-3400: long-poll input discard must not touch event loop of --- a closed connection. --- -function long() fiber.yield() return 100 end ---- -... -c = net.connect(box.cfg.listen) ---- -... -c:ping() ---- -- true -... --- Create batch of two requests. First request is sent to TX --- thread, second one terminates connection. The preceeding --- request discards input, and this operation must not trigger --- new attempts to read any data - the connection is closed --- already. --- -f = fiber.create(c._transport.perform_request, nil, nil, false, 'call_17', nil, nil, nil, 'long', {}) c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') ---- -... -while f:status() ~= 'dead' do fiber.sleep(0.01) end ---- -... -c:close() ---- -... --- --- gh-3464: iproto hangs in 100% CPU when too big packet size --- is received due to size_t overflow. --- -c = net:connect(box.cfg.listen) ---- -... -data = msgpack.encode(18400000000000000000)..'aaaaaaa' ---- -... -c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, data) ---- -- null -- Peer closed -... -c:close() ---- -... -test_run:grep_log('default', 'too big packet size in the header') ~= nil ---- -- true -... --- --- gh-3629: netbox leaks when a connection is closed deliberately --- and it has non-finished requests. --- -ready = false ---- -... -ok = nil ---- -... -err = nil ---- -... -c = net:connect(box.cfg.listen) ---- -... -function do_long() while not ready do fiber.sleep(0.01) end end ---- -... -box.schema.func.create('do_long') ---- -... -box.schema.user.grant('guest', 'execute', 'function', 'do_long') ---- -... -f = fiber.create(function() ok, err = pcall(c.call, c, 'do_long') end) ---- -... -while f:status() ~= 'suspended' do fiber.sleep(0.01) end ---- -... -c:close() ---- -... -ready = true ---- -... -while not err do fiber.sleep(0.01) end ---- -... -ok, err ---- -- false -- Connection closed -... --- --- gh-3856: wait_connected = false is ignored. --- -c = net.connect('8.8.8.8:123456', {wait_connected = false}) ---- -... -c ---- -- opts: - wait_connected: false - host: 8.8.8.8 - state: initial - port: '123456' -... -c:close() ---- -... -box.schema.func.drop('do_long') ---- -... -box.schema.user.revoke('guest', 'write', 'space', '_schema') ---- -... -box.schema.user.revoke('guest', 'read,write', 'space', '_space') ---- -... -box.schema.user.revoke('guest', 'create', 'space') ---- -... --- --- gh-3958 updating box.cfg.readahead doesn't affect existing connections. --- -readahead = box.cfg.readahead ---- -... -box.cfg{readahead = 128} ---- -... -s = box.schema.space.create("test") ---- -... -_ = s:create_index("pk") ---- -... -box.schema.user.grant("guest", "read,write", "space", "test") ---- -... --- connection is created with small readahead value, --- make sure it is updated if box.cfg.readahead is changed. -c = net.connect(box.cfg.listen) ---- -... -box.cfg{readahead = 100 * 1024} ---- -... -box.error.injection.set("ERRINJ_WAL_DELAY", true) ---- -- ok -... -pad = string.rep('x', 8192) ---- -... -for i = 1, 5 do c.space.test:replace({i, pad}, {is_async = true}) end ---- -... -box.error.injection.set("ERRINJ_WAL_DELAY", false) ---- -- ok -... -test_run:wait_log('default', 'readahead limit is reached', 1024, 0.1) ---- -... -s:drop() ---- -... -box.cfg{readahead = readahead} ---- -... --- --- related to gh-4040: log corrupted rows --- -log_level = box.cfg.log_level ---- -... -box.cfg{log_level=6} ---- -... -sock = socket.tcp_connect(LISTEN.host, LISTEN.service) ---- -... -sock:read(9) ---- -- Tarantool -... --- we need to have a packet with correctly encoded length, --- so that it bypasses iproto length check, but cannot be --- decoded in xrow_header_decode --- 0x3C = 60, sha1 digest is 20 bytes long -data = string.fromhex('3C'..string.rep(require('digest').sha1_hex('bcde'), 3)) ---- -... -sock:write(data) ---- -- 61 -... -sock:close() ---- -- true -... -test_run:wait_log('default', 'Got a corrupted row.*', nil, 10) ---- -- 'Got a corrupted row:' -... -test_run:wait_log('default', '00000000:.*', nil, 10) ---- -- '00000000: A3 02 D6 5A E4 D9 E7 68 A1 53 8D 53 60 5F 20 3F ' -... -test_run:wait_log('default', '00000010:.*', nil, 10) ---- -- '00000010: D8 E2 D6 E2 A3 02 D6 5A E4 D9 E7 68 A1 53 8D 53 ' -... -test_run:wait_log('default', '00000020:.*', nil, 10) ---- -- '00000020: 60 5F 20 3F D8 E2 D6 E2 A3 02 D6 5A E4 D9 E7 68 ' -... -test_run:wait_log('default', '00000030:.*', nil, 10) ---- -- '00000030: A1 53 8D 53 60 5F 20 3F D8 E2 D6 E2 ' -... --- we expect nothing below, so don't wait -test_run:grep_log('default', '00000040:.*') ---- -- null -... -box.cfg{log_level=log_level} ---- -... diff --git a/test/box/net.box.test.lua b/test/box/net.box.test.lua deleted file mode 100644 index 8e65ff470..000000000 --- a/test/box/net.box.test.lua +++ /dev/null @@ -1,1585 +0,0 @@ -remote = require 'net.box' -fiber = require 'fiber' -log = require 'log' -msgpack = require 'msgpack' -env = require('test_run') -test_run = env.new() -test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") - -test_run:cmd("setopt delimiter ';'") -function x_select(cn, space_id, index_id, iterator, offset, limit, key, opts) - local ret = cn:_request('select', opts, nil, space_id, index_id, iterator, - offset, limit, key) - return ret -end -function x_fatal(cn) cn._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') end -test_run:cmd("setopt delimiter ''"); - -LISTEN = require('uri').parse(box.cfg.listen) -space = box.schema.space.create('net_box_test_space') -index = space:create_index('primary', { type = 'tree' }) - --- low level connection -log.info("create connection") -cn = remote.connect(LISTEN.host, LISTEN.service) -log.info("state is %s", cn.state) - -cn:ping() -log.info("ping is done") -cn:ping() -log.info("ping is done") - - -cn:ping() - - --- check permissions -cn:call('unexists_procedure') -function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end -cn:call('test_foo', {'a', 'b', 'c'}) -cn:eval('return 2+2') -cn:close() --- connect and call without usage access -box.schema.user.grant('guest','execute','universe') -box.schema.user.revoke('guest','usage','universe') -box.session.su("guest") -cn = remote.connect(LISTEN.host, LISTEN.service) -cn:call('test_foo', {'a', 'b', 'c'}) -box.session.su("admin") -box.schema.user.grant('guest','usage','universe') -cn:close() -cn = remote.connect(box.cfg.listen) - -cn:call('unexists_procedure') -cn:call('test_foo', {'a', 'b', 'c'}) -cn:call(nil, {'a', 'b', 'c'}) -cn:eval('return 2+2') -cn:eval('return 1, 2, 3') -cn:eval('return ...', {1, 2, 3}) -cn:eval('return { k = "v1" }, true, { xx = 10, yy = 15 }, nil') -cn:eval('return nil') -cn:eval('return') -cn:eval('error("exception")') -cn:eval('box.error(0)') -cn:eval('!invalid expression') - --- box.commit() missing at return of CALL/EVAL -function no_commit() box.begin() fiber.sleep(0.001) end -cn:call('no_commit') -cn:eval('no_commit()') - -remote.self:eval('return 1+1, 2+2') -remote.self:eval('return') -remote.self:eval('error("exception")') -remote.self:eval('box.error(0)') -remote.self:eval('!invalid expression') - -box.schema.user.revoke('guest', 'execute', 'universe') - --- --- gh-822: net.box.call should roll back local transaction on error --- - -_ = box.schema.space.create('gh822') -_ = box.space.gh822:create_index('primary') - -test_run:cmd("setopt delimiter ';'") - --- rollback on invalid function -function rollback_on_invalid_function() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.call, remote.self, 'invalid_function') - return box.space.gh822:get(1) == nil -end; -rollback_on_invalid_function(); - --- rollback on call error -function test_error() error('Some error') end; -function rollback_on_call_error() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.call, remote.self, 'test_error') - return box.space.gh822:get(1) == nil -end; -rollback_on_call_error(); - --- rollback on eval -function rollback_on_eval_error() - box.begin() - box.space.gh822:insert{1, "netbox_test"} - pcall(remote.self.eval, remote.self, "error('Some error')") - return box.space.gh822:get(1) == nil -end; -rollback_on_eval_error(); - -test_run:cmd("setopt delimiter ''"); -box.space.gh822:drop() - -box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') -box.schema.user.grant('guest', 'execute', 'universe') - -cn:close() -cn = remote.connect(box.cfg.listen) - -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0xFFFFFFFF, 123) -space:insert{123, 345} -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0, 123) -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 1, 123) -x_select(cn, space.id, space.index.primary.id, box.index.EQ, 1, 1, 123) - -cn.space[space.id] ~= nil -cn.space.net_box_test_space ~= nil -cn.space.net_box_test_space ~= nil -cn.space.net_box_test_space.index ~= nil -cn.space.net_box_test_space.index.primary ~= nil -cn.space.net_box_test_space.index[space.index.primary.id] ~= nil - - -cn.space.net_box_test_space.index.primary:select(123) -cn.space.net_box_test_space.index.primary:select(123, { limit = 0 }) -cn.space.net_box_test_space.index.primary:select(nil, { limit = 1, }) -cn.space.net_box_test_space:insert{234, 1,2,3} -cn.space.net_box_test_space:insert{234, 1,2,3} -cn.space.net_box_test_space.insert{234, 1,2,3} - -cn.space.net_box_test_space:replace{354, 1,2,3} -cn.space.net_box_test_space:replace{354, 1,2,4} - -cn.space.net_box_test_space:select{123} -space:select({123}, { iterator = 'GE' }) -cn.space.net_box_test_space:select({123}, { iterator = 'GE' }) -cn.space.net_box_test_space:select({123}, { iterator = 'GT' }) -cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1 }) -cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1, offset = 1 }) - -cn.space.net_box_test_space:select{123} -cn.space.net_box_test_space:update({123}, { { '+', 2, 1 } }) -cn.space.net_box_test_space:update(123, { { '+', 2, 1 } }) -cn.space.net_box_test_space:select{123} - -cn.space.net_box_test_space:insert(cn.space.net_box_test_space:get{123}:update{ { '=', 1, 2 } }) -cn.space.net_box_test_space:delete{123} -cn.space.net_box_test_space:select{2} -cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) - -cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) - -cn.space.net_box_test_space:delete{1} -cn.space.net_box_test_space:delete{2} -cn.space.net_box_test_space:delete{2} - --- test one-based indexing in splice operation (see update.test.lua) -cn.space.net_box_test_space:replace({10, 'abcde'}) -cn.space.net_box_test_space:update(10, {{':', 2, 0, 0, '!'}}) -cn.space.net_box_test_space:update(10, {{':', 2, 1, 0, '('}}) -cn.space.net_box_test_space:update(10, {{':', 2, 2, 0, '({'}}) -cn.space.net_box_test_space:update(10, {{':', 2, -1, 0, ')'}}) -cn.space.net_box_test_space:update(10, {{':', 2, -2, 0, '})'}}) -cn.space.net_box_test_space:delete{10} - -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) --- gh-841: net.box uses incorrect iterator type for select with no arguments -cn.space.net_box_test_space:select() - -cn.space.net_box_test_space.index.primary:min() -cn.space.net_box_test_space.index.primary:min(354) -cn.space.net_box_test_space.index.primary:max() -cn.space.net_box_test_space.index.primary:max(234) -cn.space.net_box_test_space.index.primary:count() -cn.space.net_box_test_space.index.primary:count(354) - -cn.space.net_box_test_space:get(354) - --- reconnects after errors - -box.schema.user.revoke('guest', 'execute', 'universe') -box.schema.func.create('test_foo') -box.schema.user.grant('guest', 'execute', 'function', 'test_foo') - --- -- 1. no reconnect -x_fatal(cn) -cn.state -cn:ping() -cn:call('test_foo') -cn:wait_state('active') - --- -- 2 reconnect -cn = remote.connect(LISTEN.host, LISTEN.service, { reconnect_after = .1 }) -cn.space ~= nil - -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) -x_fatal(cn) -cn:wait_connected() -cn:wait_state('active') -cn:wait_state({active=true}) -cn:ping() -cn.state -cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) - -x_fatal(cn) -x_select(cn, space.id, 0, box.index.ALL, 0, 0xFFFFFFFF, {}) - -cn.state -cn:ping() - --- -- dot-new-method - -cn1 = remote.new(LISTEN.host, LISTEN.service) -x_select(cn1, space.id, 0, box.index.ALL, 0, 0xFFFFFFF, {}) -cn1:close() --- -- error while waiting for response -type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end)) -function pause() fiber.sleep(10) return true end - -box.schema.func.create('pause') -box.schema.user.grant('guest', 'execute', 'function', 'pause') -cn:call('pause') -cn:call('test_foo', {'a', 'b', 'c'}) -box.schema.func.drop('pause') - --- call -remote.self:call('test_foo', {'a', 'b', 'c'}) -cn:call('test_foo', {'a', 'b', 'c'}) -box.schema.func.drop('test_foo') - -box.schema.func.create('long_rep') -box.schema.user.grant('guest', 'execute', 'function', 'long_rep') - --- long replies -function long_rep() return { 1, string.rep('a', 5000) } end -res = cn:call('long_rep') -res[1] == 1 -res[2] == string.rep('a', 5000) - -function long_rep() return { 1, string.rep('a', 50000) } end -res = cn:call('long_rep') -res[1] == 1 -res[2] == string.rep('a', 50000) - -box.schema.func.drop('long_rep') - --- a.b.c.d -u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E' -X = {} -X.X = X -function X.fn(x,y) return y or x end -box.schema.user.grant('guest', 'execute', 'universe') -cn:close() -cn = remote.connect(LISTEN.host, LISTEN.service) -cn:call('X.fn', {u}) -cn:call('X.X.X.X.X.X.X.fn', {u}) -cn:call('X.X.X.X:fn', {u}) -box.schema.user.revoke('guest', 'execute', 'universe') -cn:close() - --- auth - -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123', wait_connected = true }) -cn:is_connected() -cn.error -cn.state - - -box.schema.user.create('netbox', { password = 'test' }) -box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') -box.schema.user.grant('netbox', 'execute', 'universe') -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' }) -cn.state -cn.error -cn:ping() - -function ret_after(to) fiber.sleep(to) return {{to}} end - -cn:ping({timeout = 1.00}) -cn:ping({timeout = 1e-9}) -cn:ping() - -remote_space = cn.space.net_box_test_space -remote_pk = remote_space.index.primary - -remote_space:insert({0}, { timeout = 1.00 }) -remote_space:insert({1}, { timeout = 1e-9 }) -remote_space:insert({2}) - -remote_space:replace({0}, { timeout = 1e-9 }) -remote_space:replace({1}) -remote_space:replace({2}, { timeout = 1.00 }) - -remote_space:upsert({3}, {}, { timeout = 1e-9 }) -remote_space:upsert({4}, {}) -remote_space:upsert({5}, {}, { timeout = 1.00 }) -remote_space:upsert({3}, {}) - -remote_space:update({3}, {}, { timeout = 1e-9 }) -remote_space:update({4}, {}) -remote_space:update({5}, {}, { timeout = 1.00 }) -remote_space:update({3}, {}) - -remote_pk:update({5}, {}, { timeout = 1e-9 }) -remote_pk:update({4}, {}) -remote_pk:update({3}, {}, { timeout = 1.00 }) -remote_pk:update({5}, {}) - -remote_space:get({0}) -remote_space:get({1}, { timeout = 1.00 }) -remote_space:get({2}, { timeout = 1e-9 }) - -remote_pk:get({3}, { timeout = 1e-9 }) -remote_pk:get({4}) -remote_pk:get({5}, { timeout = 1.00 }) - -remote_space:select({2}, { timeout = 1e-9 }) -remote_space:select({2}, { timeout = 1.00 }) -remote_space:select({2}) - -remote_pk:select({2}, { timeout = 1.00 }) -remote_pk:select({2}, { timeout = 1e-9 }) -remote_pk:select({2}) - -remote_space:select({5}, { timeout = 1.00, iterator = 'LE', limit = 5 }) -remote_space:select({5}, { iterator = 'LE', limit = 5}) -remote_space:select({5}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) - -remote_pk:select({2}, { timeout = 1.00, iterator = 'LE', limit = 5 }) -remote_pk:select({2}, { iterator = 'LE', limit = 5}) -remote_pk:select({2}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) - -remote_pk:count({2}, { timeout = 1.00}) -remote_pk:count({2}, { timeout = 1e-9}) -remote_pk:count({2}) - -remote_pk:count({2}, { timeout = 1.00, iterator = 'LE' }) -remote_pk:count({2}, { iterator = 'LE'}) -remote_pk:count({2}, { timeout = 1e-9, iterator = 'LE' }) - -remote_pk:min(nil, { timeout = 1.00 }) -remote_pk:min(nil, { timeout = 1e-9 }) -remote_pk:min(nil) - -remote_pk:min({0}, { timeout = 1e-9 }) -remote_pk:min({1}) -remote_pk:min({2}, { timeout = 1.00 }) - -remote_pk:max(nil) -remote_pk:max(nil, { timeout = 1e-9 }) -remote_pk:max(nil, { timeout = 1.00 }) - -remote_pk:max({0}, { timeout = 1.00 }) -remote_pk:max({1}, { timeout = 1e-9 }) -remote_pk:max({2}) - --- --- gh-3262: index:count() inconsistent results --- -test_run:cmd("setopt delimiter ';'") - -function do_count_test(min, it) - local r1 = remote_pk:count(min, {iterator = it} ) - local r2 = box.space.net_box_test_space.index.primary:count(min, {iterator = it} ) - local r3 = remote.self.space.net_box_test_space.index.primary:count(min, {iterator = it} ) - return r1 == r2 and r2 == r3 -end; - -data = remote_pk:select(); - -for _, v in pairs(data) do - local itrs = {'GE', 'GT', 'LE', 'LT' } - for _, it in pairs(itrs) do - assert(do_count_test(v[0], it) == true) - end -end; - -test_run:cmd("setopt delimiter ''"); - -_ = remote_space:delete({0}, { timeout = 1e-9 }) -_ = remote_pk:delete({0}, { timeout = 1.00 }) -_ = remote_space:delete({1}, { timeout = 1.00 }) -_ = remote_pk:delete({1}, { timeout = 1e-9 }) -_ = remote_space:delete({2}, { timeout = 1e-9 }) -_ = remote_pk:delete({2}) -_ = remote_pk:delete({3}) -_ = remote_pk:delete({4}) -_ = remote_pk:delete({5}) - -remote_space:get(0) -remote_space:get(1) -remote_space:get(2) - -remote_space = nil - -cn:call('ret_after', {0.01}, { timeout = 1.00 }) -cn:call('ret_after', {1.00}, { timeout = 1e-9 }) - -cn:eval('return ret_after(...)', {0.01}, { timeout = 1.00 }) -cn:eval('return ret_after(...)', {1.00}, { timeout = 1e-9 }) - --- --- :timeout() --- @deprecated since 1.7.4 --- - -cn:timeout(1).space.net_box_test_space.index.primary:select{234} -cn:call('ret_after', {.01}) -cn:timeout(1):call('ret_after', {.01}) -cn:timeout(.01):call('ret_after', {1}) - -cn = remote:timeout(0.0000000001):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) -cn:close() -cn = remote:timeout(1):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) - -remote.self:ping() -remote.self.space.net_box_test_space:select{234} -remote.self:timeout(123).space.net_box_test_space:select{234} -remote.self:is_connected() -remote.self:wait_connected() - -cn:close() --- cleanup database after tests -space:drop() - --- #1545 empty password -cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'test' }) -cn ~= nil -cn:close() -cn = remote.connect(LISTEN.host, LISTEN.service, { password = 'test' }) -cn ~= nil -cn:close() - --- #544 usage for remote[point]method -cn = remote.connect(LISTEN.host, LISTEN.service) - -box.schema.user.grant('guest', 'execute', 'universe') -cn:close() -cn = remote.connect(LISTEN.host, LISTEN.service) -cn:eval('return true') -cn.eval('return true') - -cn.ping() - -cn:close() - -remote.self:eval('return true') -remote.self.eval('return true') -box.schema.user.revoke('guest', 'execute', 'universe') - --- uri as the first argument -uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service) - -cn = remote.new(uri) -cn:ping() -cn:close() - -uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) -cn = remote.new(uri) -cn ~= nil, cn.state, cn.error -cn:close() --- don't merge creds from uri & opts -remote.new(uri, { password = 'test' }) -cn = remote.new(uri, { user = 'netbox', password = 'test' }) -cn:ping() -cn:close() - -box.schema.user.drop('netbox') - --- #594: bad argument #1 to 'setmetatable' (table expected, got number) -box.schema.func.create('dostring') -box.schema.user.grant('guest', 'execute', 'function', 'dostring') -test_run:cmd("setopt delimiter ';'") -function gh594() - local cn = remote.connect(box.cfg.listen) - local ping = fiber.create(function() cn:ping() end) - cn:call('dostring', {'return 2 + 2'}) - cn:close() -end; -test_run:cmd("setopt delimiter ''"); -gh594() -box.schema.func.drop('dostring') - - --- #636: Reload schema on demand -sp = box.schema.space.create('test_old') -_ = sp:create_index('primary') -sp:insert{1, 2, 3} - -box.schema.user.grant('guest', 'read', 'space', 'test_old') -con = remote.new(box.cfg.listen) -con:ping() -con.space.test_old:select{} -con.space.test == nil - -sp = box.schema.space.create('test') -_ = sp:create_index('primary') -sp:insert{2, 3, 4} - -box.schema.user.grant('guest', 'read', 'space', 'test') - -con.space.test == nil -con:reload_schema() -con.space.test:select{} - -box.space.test:drop() -box.space.test_old:drop() -con:close() - -name = string.match(arg[0], "([^,]+)%.lua") -file_log = require('fio').open(name .. '.log', {'O_RDONLY', 'O_NONBLOCK'}) -file_log:seek(0, 'SEEK_END') ~= 0 - -box.schema.user.grant('guest', 'execute', 'universe') -test_run:cmd("setopt delimiter ';'") - -_ = fiber.create( - function() - local conn = require('net.box').new(box.cfg.listen) - conn:call('no_such_function', {}) - conn:close() - end -); -test_run:cmd("setopt delimiter ''"); -test_run:wait_log('default', 'ER_NO_SUCH_PROC', nil, 10) -box.schema.user.revoke('guest', 'execute', 'universe') - --- --- gh-3900: tarantool can be crashed by sending gibberish to a --- binary socket --- -socket = require("socket") -sock = socket.tcp_connect(LISTEN.host, LISTEN.service) -data = string.fromhex("6783000000000000000000000000000000000000000000800000C8000000000000000000000000000000000000000000FFFF210100373208000000FFFF000055AAEB66486472530D02000000000010A0350001008000001000000000000000000000000000D05700") -sock:write(data) -test_run:wait_log('default', 'ER_INVALID_MSGPACK: Invalid MsgPack %- packet body', nil, 10) -sock:close() - --- gh-983 selecting a lot of data crashes the server or hangs the --- connection - --- gh-983 test case: iproto connection selecting a lot of data -_ = box.schema.space.create('test', { temporary = true }) -_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) - -data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhh" - -for i = 0,10000 do box.space.test:insert{i, data1k} end - -box.schema.user.grant('guest', 'read', 'space', 'test') -net = require('net.box') -c = net:connect(box.cfg.listen) -r = c.space.test:select(nil, {limit=5000}) -box.space.test:drop() - --- gh-970 gh-971 UPSERT over network -_ = box.schema.space.create('test') -_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) -_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) -_ = box.space.test:insert{1, 2, "string"} -box.schema.user.grant('guest', 'read,write', 'space', 'test') -c = net:connect(box.cfg.listen) -c.space.test:select{} -c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update -c.space.test:select{} -c.space.test:upsert({2, 4, 'something'}, {{'+', 2, 1}}) -- insert -c.space.test:select{} -c.space.test:upsert({2, 4, 'nothing'}, {{'+', 3, 100500}}) -- wrong operation -c.space.test:select{} - --- gh-1729 net.box index metadata incompatible with local metadata -c.space.test.index.primary.parts -c.space.test.index.covering.parts - -box.space.test:drop() - --- CALL vs CALL_16 in connect options -function echo(...) return ... end -box.schema.user.grant('guest', 'execute', 'universe') -c = net.connect(box.cfg.listen) -c:call('echo', {42}) -c:eval('return echo(...)', {42}) --- invalid arguments -c:call('echo', 42) -c:eval('return echo(...)', 42) -c:close() -c = net.connect(box.cfg.listen, {call_16 = true}) -c:call('echo', 42) -c:eval('return echo(...)', 42) -c:close() -box.schema.user.revoke('guest', 'execute', 'universe') - --- --- gh-2195 export pure msgpack from net.box --- - -space = box.schema.space.create('test') -_ = box.space.test:create_index('primary') -box.schema.user.grant('guest', 'read,write', 'space', 'test') -box.schema.user.grant('guest', 'execute', 'universe') -c = net.connect(box.cfg.listen) -ibuf = require('buffer').ibuf() - -c:ping() -c.space.test ~= nil - -c.space.test:replace({1, 'hello'}) - --- replace -c.space.test:replace({2}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- replace + skip_header -c.space.test:replace({2}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- insert -c.space.test:insert({3}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- insert + skip_header -_ = space:delete({3}) -c.space.test:insert({3}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- update -c.space.test:update({3}, {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c.space.test.index.primary:update({3}, {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- update + skip_header -c.space.test:update({3}, {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c.space.test.index.primary:update({3}, {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- upsert -c.space.test:upsert({4}, {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- upsert + skip_header -c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- delete -c.space.test:upsert({4}, {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- delete + skip_header -c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- select -c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- select + skip_header -c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- select -len = c.space.test:select({}, {buffer = ibuf}) -ibuf.rpos + len == ibuf.wpos -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -ibuf.rpos == ibuf.wpos -len -result - --- select + skip_header -len = c.space.test:select({}, {buffer = ibuf, skip_header = true}) -ibuf.rpos + len == ibuf.wpos -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -ibuf.rpos == ibuf.wpos -len -result - --- call -c:call("echo", {1, 2, 3}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:call("echo", {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:call("echo", nil, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- call + skip_header -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:call("echo", {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:call("echo", nil, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- eval -c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:eval("echo(...)", {}, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:eval("echo(...)", nil, {buffer = ibuf}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- eval + skip_header -c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:eval("echo(...)", {}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -c:eval("echo(...)", nil, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- make several request into a buffer with skip_header, then read --- results -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) -c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - --- unsupported methods -c.space.test:get({1}, { buffer = ibuf}) -c.space.test.index.primary:min({}, { buffer = ibuf}) -c.space.test.index.primary:max({}, { buffer = ibuf}) -c.space.test.index.primary:count({}, { buffer = ibuf}) -c.space.test.index.primary:get({1}, { buffer = ibuf}) - --- error handling -rpos, wpos = ibuf.rpos, ibuf.wpos -c.space.test:insert({1}, {buffer = ibuf}) -ibuf.rpos == rpos, ibuf.wpos == wpos - -ibuf = nil -c:close() -space:drop() -box.schema.user.revoke('guest', 'execute', 'universe') - --- gh-1904 net.box hangs in :close() if a fiber was cancelled --- while blocked in :_wait_state() in :_request() -options = {user = 'netbox', password = 'badpass', wait_connected = false, reconnect_after = 0.01} -c = net:new(box.cfg.listen, options) -f = fiber.create(function() c:call("") end) -fiber.sleep(0.01) -f:cancel(); c:close() - -box.schema.user.grant('guest', 'read', 'space', '_schema') - --- check for on_schema_reload callback -test_run:cmd("setopt delimiter ';'") -do - local a = 0 - function osr_cb() - a = a + 1 - end - local con = net.new(box.cfg.listen, { - wait_connected = false - }) - con:on_schema_reload(osr_cb) - con:wait_connected() - con.space._schema:select{} - box.schema.space.create('misisipi') - box.space.misisipi:drop() - con.space._schema:select{} - con:close() - con = nil - - return a -end; -do - local a = 0 - function osr_cb() - a = a + 1 - end - local con = net.new(box.cfg.listen, { - wait_connected = true - }) - con:on_schema_reload(osr_cb) - con.space._schema:select{} - box.schema.space.create('misisipi') - box.space.misisipi:drop() - con.space._schema:select{} - con:close() - con = nil - - return a -end; -test_run:cmd("setopt delimiter ''"); - -box.schema.user.revoke('guest', 'read', 'space', '_schema') - --- Tarantool < 1.7.1 compatibility (gh-1533) -c = net.new(box.cfg.listen) -c:ping() -c:close() - --- Test for connect_timeout > 0 in netbox connect -test_run:cmd("setopt delimiter ';'"); -need_stop = false; -greeting = -"Tarantool 1.7.3 (Lua console)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" .. -"type 'help' for interactive help~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; -socket = require('socket'); -srv = socket.tcp_server('localhost', 0, { - handler = function(fd) - local fiber = require('fiber') - while not need_stop do - fiber.sleep(0.01) - end - fd:write(greeting) - end -}); -port = srv:name().port --- we must get timeout -nb = net.new('localhost:' .. port, { - wait_connected = true, console = true, - connect_timeout = 0.1 -}); -nb.error:find('timed out') ~= nil; -need_stop = true -nb:close(); --- we must get peer closed -nb = net.new('localhost:' .. port, { - wait_connected = true, console = true, - connect_timeout = 0.2 -}); -nb.error ~= "Timeout exceeded"; -nb:close(); -test_run:cmd("setopt delimiter ''"); -srv:close() - -test_run:cmd("clear filter") - --- --- gh-2402 net.box doesn't support space:format() --- - -space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) -space ~= nil -_ = box.space.test:create_index('primary') -box.schema.user.grant('guest', 'read', 'space', 'test') - -c = net.connect(box.cfg.listen) - -c:ping() -c.space.test ~= nil - -format = c.space.test:format() - -format[1] ~= nil -format[1].name == "id" -format[1].type == "unsigned" - -c.space.test:format({}) - --- --- gh-4091: index unique flag is always false. --- -c.space.test.index.primary.unique - -c:close() -space:drop() - --- --- Check that it's possible to get connection object form net.box space --- - -space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) -space ~= nil -_ = box.space.test:create_index('primary') -box.schema.user.grant('guest','read,write,execute','space', 'test') - -c = net.connect(box.cfg.listen) - -c:ping() -c.space.test ~= nil - -c.space.test.connection == c -box.schema.user.revoke('guest','read,write,execute','space', 'test') -c:close() - --- --- gh-2642: box.session.type() --- - -box.schema.user.grant('guest','execute','universe') -c = net.connect(box.cfg.listen) -c:call("box.session.type") -c:close() -box.schema.user.revoke('guest', 'execute', 'universe') - - --- --- On_connect/disconnect triggers. --- -test_run:cmd('create server connecter with script = "box/proxy.lua"') -test_run:cmd('start server connecter') -test_run:cmd("set variable connect_to to 'connecter.listen'") -conn = net.connect(connect_to, { reconnect_after = 0.1 }) -conn.state -connected_cnt = 0 -disconnected_cnt = 0 -function on_connect() connected_cnt = connected_cnt + 1 end -function on_disconnect() disconnected_cnt = disconnected_cnt + 1 end -conn:on_connect(on_connect) -conn:on_disconnect(on_disconnect) -test_run:cmd('stop server connecter') -test_run:cmd('start server connecter') -while conn.state ~= 'active' do fiber.sleep(0.1) end -connected_cnt -old_disconnected_cnt = disconnected_cnt -disconnected_cnt >= 1 -conn:close() -disconnected_cnt == old_disconnected_cnt + 1 -test_run:cmd('stop server connecter') - --- --- gh-2401 update pseudo objects not replace them --- -space:drop() -space = box.schema.space.create('test') -box.schema.user.grant('guest', 'read', 'space', 'test') -c = net.connect(box.cfg.listen) -cspace = c.space.test -space.index.test_index == nil -cspace.index.test_index == nil -_ = space:create_index("test_index", {parts={1, 'string'}}) -c:reload_schema() -space.index.test_index ~= nil -cspace.index.test_index ~= nil -c.space.test.index.test_index ~= nil - --- cleanup - -space:drop() - --- --- gh-946: long polling CALL blocks input --- -box.schema.func.create('fast_call') -box.schema.func.create('long_call') -box.schema.func.create('wait_signal') -box.schema.user.grant('guest', 'execute', 'function', 'fast_call') -box.schema.user.grant('guest', 'execute', 'function', 'long_call') -box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') -c = net.connect(box.cfg.listen) - -N = 100 - -pad = string.rep('x', 1024) - -long_call_cond = fiber.cond() -long_call_channel = fiber.channel() -fast_call_channel = fiber.channel() - -function fast_call(x) return x end -function long_call(x) long_call_cond:wait() return x * 2 end - -test_run:cmd("setopt delimiter ';'") -for i = 1, N do - fiber.create(function() - fast_call_channel:put(c:call('fast_call', {i, pad})) - end) - fiber.create(function() - long_call_channel:put(c:call('long_call', {i, pad})) - end) -end -test_run:cmd("setopt delimiter ''"); - -x = 0 -for i = 1, N do x = x + fast_call_channel:get() end -x - -long_call_cond:broadcast() - -x = 0 -for i = 1, N do x = x + long_call_channel:get() end -x - --- --- Check that a connection does not leak if there is --- a long CALL in progress when it is closed. --- -disconnected = false -function on_disconnect() disconnected = true end - --- Make sure all dangling connections are collected so --- that on_disconnect trigger isn't called spuriously. -collectgarbage('collect') -fiber.sleep(0) - -box.session.on_disconnect(on_disconnect) == on_disconnect - --- --- gh-3859: on_disconnect is called only after all requests are --- processed, but should be called right after disconnect and --- only once. --- -ch1 = fiber.channel(1) -ch2 = fiber.channel(1) -function wait_signal() ch1:put(true) ch2:get() end -_ = fiber.create(function() c:call('wait_signal') end) -ch1:get() - -c:close() -fiber.sleep(0) -while disconnected == false do fiber.sleep(0.01) end -disconnected -- true -disconnected = nil - -ch2:put(true) -fiber.sleep(0) -disconnected -- nil, on_disconnect is not called second time. - -box.session.on_disconnect(nil, on_disconnect) - -box.schema.func.drop('long_call') -box.schema.func.drop('fast_call') -box.schema.func.drop('wait_signal') --- --- gh-2666: check that netbox.call is not repeated on schema --- change. --- -box.schema.user.grant('guest', 'write', 'space', '_space') -box.schema.user.grant('guest', 'write', 'space', '_schema') -box.schema.user.grant('guest', 'create', 'universe') -count = 0 -function create_space(name) count = count + 1 box.schema.create_space(name) return true end -box.schema.func.create('create_space') -box.schema.user.grant('guest', 'execute', 'function', 'create_space') -c = net.connect(box.cfg.listen) -c:call('create_space', {'test1'}) -count -c:call('create_space', {'test2'}) -count -c:call('create_space', {'test3'}) -count -box.space.test1:drop() -box.space.test2:drop() -box.space.test3:drop() -box.schema.user.revoke('guest', 'write', 'space', '_space') -box.schema.user.revoke('guest', 'write', 'space', '_schema') -box.schema.user.revoke('guest', 'create', 'universe') -c:close() -box.schema.func.drop('create_space') - --- --- gh-3164: netbox connection is not closed and garbage collected --- ever, if reconnect_after is set. --- -test_run:cmd('start server connecter') -test_run:cmd("set variable connect_to to 'connecter.listen'") -weak = setmetatable({}, {__mode = 'v'}) --- Create strong and weak reference. Weak is valid until strong --- is valid too. -strong = net.connect(connect_to, {reconnect_after = 0.1}) -weak.c = strong -weak.c:ping() -test_run:cmd('stop server connecter') -test_run:cmd('cleanup server connecter') --- Check the connection tries to reconnect at least two times. --- 'Cannot assign requested address' is the crutch for running the --- tests in a docker. This error emits instead of --- 'Connection refused' inside a docker. -old_log_level = box.cfg.log_level -box.cfg{log_level = 6} -log.info(string.rep('a', 1000)) -test_run:cmd("setopt delimiter ';'") -while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and - test_run:grep_log('default', 'Connection refused', 1000) == nil and - test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do - fiber.sleep(0.1) -end; -log.info(string.rep('a', 1000)); -while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and - test_run:grep_log('default', 'Connection refused', 1000) == nil and - test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do - fiber.sleep(0.1) -end; -test_run:cmd("setopt delimiter ''"); -box.cfg{log_level = old_log_level} -collectgarbage('collect') -strong.state -strong == weak.c --- Remove single strong reference. Now connection must be garbage --- collected. -strong = nil -collectgarbage('collect') --- Now weak.c is null, because it was weak reference, and the --- connection is deleted by 'collect'. -weak.c - --- --- gh-2677: netbox supports console connections, that complicates --- both console and netbox. It was necessary because before a --- connection is established, a console does not known is it --- binary or text protocol, and netbox could not be created from --- existing socket. --- -box.schema.user.grant('guest', 'execute', 'universe') -urilib = require('uri') -uri = urilib.parse(tostring(box.cfg.listen)) -s, greeting = net.establish_connection(uri.host, uri.service) -c = net.wrap(s, greeting, uri.host, uri.service, {reconnect_after = 0.01}) -c.state - -a = 100 -function kek(args) return {1, 2, 3, args} end -c:eval('a = 200') -a -c:call('kek', {300}) -s = box.schema.create_space('test') -box.schema.user.grant('guest', 'read,write', 'space', 'test') -pk = s:create_index('pk') -c:reload_schema() -c.space.test:replace{1} -c.space.test:get{1} -c.space.test:delete{1} --- --- Break a connection to test reconnect_after. --- -_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') -while not c:is_connected() do fiber.sleep(0.01) end -c:ping() - -s:drop() -c:close() - --- --- Test a case, when netbox can not connect first time, but --- reconnect_after is set. --- -c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false}) -while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end -c:close() - -box.schema.user.revoke('guest', 'execute', 'universe') -c.state -c = nil - --- --- gh-3256 net.box is_nullable and collation options output --- -space = box.schema.create_space('test') -box.schema.user.grant('guest', 'read', 'space', 'test') -_ = space:create_index('pk') -_ = space:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}}) -c = net:connect(box.cfg.listen) -c.space.test.index.sk.parts -space:drop() - -space = box.schema.create_space('test') -c:close() -box.schema.user.grant('guest', 'read', 'space', 'test') -c = net:connect(box.cfg.listen) -box.internal.collation.create('test', 'ICU', 'ru-RU') -collation_id = box.internal.collation.id_by_name('test') -_ = space:create_index('sk', { type = 'tree', parts = {{1, 'str', collation = 'test'}}, unique = true }) -c:reload_schema() -parts = c.space.test.index.sk.parts -#parts == 1 -parts[1].fieldno == 1 -parts[1].type == 'string' -parts[1].is_nullable == false -if _TARANTOOL >= '2.2.1' then \ - return parts[1].collation == 'test' \ -else \ - return parts[1].collation_id == collation_id \ -end -c:close() -box.internal.collation.drop('test') -space:drop() -c.state -c = nil - --- --- gh-3107: fiber-async netbox. --- -cond = nil -box.schema.func.create('long_function') -box.schema.user.grant('guest', 'execute', 'function', 'long_function') -function long_function(...) cond = fiber.cond() cond:wait() return ... end -function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end -s = box.schema.create_space('test') -pk = s:create_index('pk') -s:replace{1} -s:replace{2} -s:replace{3} -s:replace{4} -c = net:connect(box.cfg.listen) --- --- Check long connections, multiple wait_result(). --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -future:result() -future:is_ready() -future:wait_result(0.01) -- Must fail on timeout. -finalize_long() -ret = future:wait_result(100) -future:is_ready() --- Any timeout is ok - response is received already. -future:wait_result(0) -future:wait_result(0.01) -ret - -_, err = pcall(future.wait_result, future, true) -err:find('Usage') ~= nil -_, err = pcall(future.wait_result, future, '100') -err:find('Usage') ~= nil - --- --- Check infinity timeout. --- -ret = nil -_ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async = true}):wait_result() end) -finalize_long() -while not ret do fiber.sleep(0.01) end -ret -c:close() -box.schema.user.grant('guest', 'execute', 'universe') -c = net:connect(box.cfg.listen) -future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true}) -future:result() -future:wait_result(0.01) -- Must fail on timeout. -finalize_long() -future:wait_result(100) - -c:close() --- --- Check that is_async does not work on a closed connection. --- -c:call('any_func', {}, {is_async = true}) - -box.schema.user.revoke('guest', 'execute', 'universe') -c = net:connect(box.cfg.listen) - --- --- Ensure the request is garbage collected both if is not used and --- if is. --- -gc_test = setmetatable({}, {__mode = 'v'}) -gc_test.future = c:call('long_function', {1, 2, 3}, {is_async = true}) -gc_test.future ~= nil -collectgarbage() -gc_test -finalize_long() - -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -collectgarbage() -future ~= nil -finalize_long() -future:wait_result(1000) -collectgarbage() -future ~= nil -gc_test.future = future -future = nil -collectgarbage() -gc_test - --- --- Ensure a request can be finalized from non-caller fibers. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -ret = {} -count = 0 -for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end -future:wait_result(0.01) -- Must fail on timeout. -finalize_long() -while count ~= 10 do fiber.sleep(0.1) end -ret - --- --- Test space methods. --- -c:close() -box.schema.user.grant('guest', 'read,write', 'space', 'test') -c = net:connect(box.cfg.listen) -future = c.space.test:select({1}, {is_async = true}) -ret = future:wait_result(100) -ret -type(ret[1]) -future = c.space.test:insert({5}, {is_async = true}) -future:wait_result(100) -s:get{5} -future = c.space.test:replace({6}, {is_async = true}) -future:wait_result(100) -s:get{6} -future = c.space.test:delete({6}, {is_async = true}) -future:wait_result(100) -s:get{6} -future = c.space.test:update({5}, {{'=', 2, 5}}, {is_async = true}) -future:wait_result(100) -s:get{5} -future = c.space.test:upsert({5}, {{'=', 2, 6}}, {is_async = true}) -future:wait_result(100) -s:get{5} -future = c.space.test:get({5}, {is_async = true}) -future:wait_result(100) - --- --- Test index methods. --- -future = c.space.test.index.pk:select({1}, {is_async = true}) -future:wait_result(100) -future = c.space.test.index.pk:get({2}, {is_async = true}) -future:wait_result(100) -future = c.space.test.index.pk:min({}, {is_async = true}) -future:wait_result(100) -future = c.space.test.index.pk:max({}, {is_async = true}) -future:wait_result(100) -c:close() -box.schema.user.grant('guest', 'execute', 'universe') -c = net:connect(box.cfg.listen) -future = c.space.test.index.pk:count({3}, {is_async = true}) -future:wait_result(100) -c:close() -box.schema.user.revoke('guest', 'execute', 'universe') -c = net:connect(box.cfg.listen) -future = c.space.test.index.pk:delete({3}, {is_async = true}) -future:wait_result(100) -s:get{3} -future = c.space.test.index.pk:update({4}, {{'=', 2, 6}}, {is_async = true}) -future:wait_result(100) -s:get{4} - --- --- Test async errors. --- -future = c.space.test:insert({1}, {is_async = true}) -future:wait_result() -future:result() - --- --- Test discard. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -future:discard() -finalize_long() -future:result() -future:wait_result(100) - --- --- Test closed connection. --- -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -finalize_long() -future:wait_result(100) -future2 = c:call('long_function', {1, 2, 3}, {is_async = true}) -c:close() -future2:wait_result(100) -future2:result() -future2:discard() --- Already successful result must be available. -future:wait_result(100) -future:result() -future:is_ready() -finalize_long() - --- --- Test reconnect. --- -c = net:connect(box.cfg.listen, {reconnect_after = 0.01}) -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') -while not c:is_connected() do fiber.sleep(0.01) end -finalize_long() -future:wait_result(100) -future:result() -future = c:call('long_function', {1, 2, 3}, {is_async = true}) -finalize_long() -future:wait_result(100) - --- --- Test raw response getting. --- -ibuf = require('buffer').ibuf() -future = c:call('long_function', {1, 2, 3}, {is_async = true, buffer = ibuf}) -finalize_long() -future:wait_result(100) -result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) -result - -box.schema.func.drop('long_function') - --- --- Test async schema version change. --- -function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end -box.schema.func.create('change_schema') -box.schema.user.grant('guest', 'execute', 'function', 'change_schema') -box.schema.user.grant('guest', 'write', 'space', '_schema') -box.schema.user.grant('guest', 'read,write', 'space', '_space') -box.schema.user.grant('guest', 'create', 'space') -future1 = c:call('change_schema', {'1'}, {is_async = true}) -future2 = c:call('change_schema', {'2'}, {is_async = true}) -future3 = c:call('change_schema', {'3'}, {is_async = true}) -future1:wait_result() -future2:wait_result() -future3:wait_result() - -c:close() -s:drop() -box.space.test1:drop() -box.space.test2:drop() -box.space.test3:drop() -box.schema.func.drop('change_schema') - --- --- gh-2978: field names for tuples received from netbox. --- -_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}}) -_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}}) -box.space.named:insert({1, 1}) -box.schema.user.grant('guest', 'read, write, execute', 'space') -cn = net.connect(box.cfg.listen) - -s = cn.space.named -s:get{1}.id -s:get{1}:tomap() -s:insert{2,3}:tomap() -s:replace{2,14}:tomap() -s:update(1, {{'+', 2, 10}}):tomap() -s:select()[1]:tomap() -s:delete({2}):tomap() - --- Check that formats changes after reload. -box.space.named:format({{name = "id2"}, {name="abc2"}}) -s:select()[1]:tomap() -cn:reload_schema() -s:select()[1]:tomap() - -cn:close() -box.space.named:drop() -box.schema.user.revoke('guest', 'read, write, execute', 'space') - --- --- gh-3400: long-poll input discard must not touch event loop of --- a closed connection. --- -function long() fiber.yield() return 100 end -c = net.connect(box.cfg.listen) -c:ping() --- Create batch of two requests. First request is sent to TX --- thread, second one terminates connection. The preceeding --- request discards input, and this operation must not trigger --- new attempts to read any data - the connection is closed --- already. --- -f = fiber.create(c._transport.perform_request, nil, nil, false, 'call_17', nil, nil, nil, 'long', {}) c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') -while f:status() ~= 'dead' do fiber.sleep(0.01) end -c:close() - --- --- gh-3464: iproto hangs in 100% CPU when too big packet size --- is received due to size_t overflow. --- -c = net:connect(box.cfg.listen) -data = msgpack.encode(18400000000000000000)..'aaaaaaa' -c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, data) -c:close() -test_run:grep_log('default', 'too big packet size in the header') ~= nil - - --- --- gh-3629: netbox leaks when a connection is closed deliberately --- and it has non-finished requests. --- -ready = false -ok = nil -err = nil -c = net:connect(box.cfg.listen) -function do_long() while not ready do fiber.sleep(0.01) end end -box.schema.func.create('do_long') -box.schema.user.grant('guest', 'execute', 'function', 'do_long') -f = fiber.create(function() ok, err = pcall(c.call, c, 'do_long') end) -while f:status() ~= 'suspended' do fiber.sleep(0.01) end -c:close() -ready = true -while not err do fiber.sleep(0.01) end -ok, err - --- --- gh-3856: wait_connected = false is ignored. --- -c = net.connect('8.8.8.8:123456', {wait_connected = false}) -c -c:close() - -box.schema.func.drop('do_long') -box.schema.user.revoke('guest', 'write', 'space', '_schema') -box.schema.user.revoke('guest', 'read,write', 'space', '_space') -box.schema.user.revoke('guest', 'create', 'space') - --- --- gh-3958 updating box.cfg.readahead doesn't affect existing connections. --- -readahead = box.cfg.readahead - -box.cfg{readahead = 128} - -s = box.schema.space.create("test") -_ = s:create_index("pk") -box.schema.user.grant("guest", "read,write", "space", "test") - --- connection is created with small readahead value, --- make sure it is updated if box.cfg.readahead is changed. -c = net.connect(box.cfg.listen) - -box.cfg{readahead = 100 * 1024} - -box.error.injection.set("ERRINJ_WAL_DELAY", true) -pad = string.rep('x', 8192) -for i = 1, 5 do c.space.test:replace({i, pad}, {is_async = true}) end -box.error.injection.set("ERRINJ_WAL_DELAY", false) - -test_run:wait_log('default', 'readahead limit is reached', 1024, 0.1) - -s:drop() -box.cfg{readahead = readahead} - --- --- related to gh-4040: log corrupted rows --- -log_level = box.cfg.log_level -box.cfg{log_level=6} -sock = socket.tcp_connect(LISTEN.host, LISTEN.service) -sock:read(9) --- we need to have a packet with correctly encoded length, --- so that it bypasses iproto length check, but cannot be --- decoded in xrow_header_decode --- 0x3C = 60, sha1 digest is 20 bytes long -data = string.fromhex('3C'..string.rep(require('digest').sha1_hex('bcde'), 3)) -sock:write(data) -sock:close() - -test_run:wait_log('default', 'Got a corrupted row.*', nil, 10) -test_run:wait_log('default', '00000000:.*', nil, 10) -test_run:wait_log('default', '00000010:.*', nil, 10) -test_run:wait_log('default', '00000020:.*', nil, 10) -test_run:wait_log('default', '00000030:.*', nil, 10) --- we expect nothing below, so don't wait -test_run:grep_log('default', '00000040:.*') - -box.cfg{log_level=log_level} diff --git a/test/box/net.box_bad_argument_gh-594.result b/test/box/net.box_bad_argument_gh-594.result new file mode 100644 index 000000000..339886eaa --- /dev/null +++ b/test/box/net.box_bad_argument_gh-594.result @@ -0,0 +1,38 @@ +remote = require 'net.box' +--- +... +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +-- #594: bad argument #1 to 'setmetatable' (table expected, got number) +box.schema.func.create('dostring') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'dostring') +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function gh594() + local cn = remote.connect(box.cfg.listen) + local ping = fiber.create(function() cn:ping() end) + cn:call('dostring', {'return 2 + 2'}) + cn:close() +end; +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +gh594() +--- +... +box.schema.func.drop('dostring') +--- +... diff --git a/test/box/net.box_bad_argument_gh-594.test.lua b/test/box/net.box_bad_argument_gh-594.test.lua new file mode 100644 index 000000000..65265cbb5 --- /dev/null +++ b/test/box/net.box_bad_argument_gh-594.test.lua @@ -0,0 +1,17 @@ +remote = require 'net.box' +fiber = require 'fiber' +test_run = require('test_run').new() + +-- #594: bad argument #1 to 'setmetatable' (table expected, got number) +box.schema.func.create('dostring') +box.schema.user.grant('guest', 'execute', 'function', 'dostring') +test_run:cmd("setopt delimiter ';'") +function gh594() + local cn = remote.connect(box.cfg.listen) + local ping = fiber.create(function() cn:ping() end) + cn:call('dostring', {'return 2 + 2'}) + cn:close() +end; +test_run:cmd("setopt delimiter ''"); +gh594() +box.schema.func.drop('dostring') diff --git a/test/box/net.box_call_blocks_gh-946.result b/test/box/net.box_call_blocks_gh-946.result new file mode 100644 index 000000000..40afec416 --- /dev/null +++ b/test/box/net.box_call_blocks_gh-946.result @@ -0,0 +1,124 @@ +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +--space = box.schema.space.create('net_box_test_space') +--index = space:create_index('primary', { type = 'tree' }) +net = require('net.box') +--- +... +socket = require('socket'); +--- +... +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +-- +-- gh-946: long polling CALL blocks input +-- +box.schema.func.create('fast_call') +--- +... +box.schema.func.create('long_call') +--- +... +box.schema.func.create('wait_signal') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'fast_call') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_call') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') +--- +... +c = net.connect(box.cfg.listen) +--- +... +N = 100 +--- +... +pad = string.rep('x', 1024) +--- +... +long_call_cond = fiber.cond() +--- +... +long_call_channel = fiber.channel() +--- +... +fast_call_channel = fiber.channel() +--- +... +function fast_call(x) return x end +--- +... +function long_call(x) long_call_cond:wait() return x * 2 end +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +for i = 1, N do + fiber.create(function() + fast_call_channel:put(c:call('fast_call', {i, pad})) + end) + fiber.create(function() + long_call_channel:put(c:call('long_call', {i, pad})) + end) +end +test_run:cmd("setopt delimiter ''"); +--- +... +x = 0 +--- +... +for i = 1, N do x = x + fast_call_channel:get() end +--- +... +x +--- +- 5050 +... +long_call_cond:broadcast() +--- +... +x = 0 +--- +... +for i = 1, N do x = x + long_call_channel:get() end +--- +... +x +--- +- 10100 +... +-- +-- Check that a connection does not leak if there is +-- a long CALL in progress when it is closed. +-- +disconnected = false +--- +... +function on_disconnect() disconnected = true end +--- +... +-- Make sure all dangling connections are collected so +-- that on_disconnect trigger isn't called spuriously. +collectgarbage('collect') +--- +- 0 +... +fiber.sleep(0) +--- +... +box.session.on_disconnect(on_disconnect) == on_disconnect +--- +- true +... diff --git a/test/box/net.box_call_blocks_gh-946.test.lua b/test/box/net.box_call_blocks_gh-946.test.lua new file mode 100644 index 000000000..f3cd3f305 --- /dev/null +++ b/test/box/net.box_call_blocks_gh-946.test.lua @@ -0,0 +1,67 @@ +fiber = require 'fiber' +test_run = require('test_run').new() + +--space = box.schema.space.create('net_box_test_space') +--index = space:create_index('primary', { type = 'tree' }) + +net = require('net.box') +socket = require('socket'); + +test_run:cmd('create server connecter with script = "box/proxy.lua"') + +-- +-- gh-946: long polling CALL blocks input +-- +box.schema.func.create('fast_call') +box.schema.func.create('long_call') +box.schema.func.create('wait_signal') +box.schema.user.grant('guest', 'execute', 'function', 'fast_call') +box.schema.user.grant('guest', 'execute', 'function', 'long_call') +box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') +c = net.connect(box.cfg.listen) + +N = 100 + +pad = string.rep('x', 1024) + +long_call_cond = fiber.cond() +long_call_channel = fiber.channel() +fast_call_channel = fiber.channel() + +function fast_call(x) return x end +function long_call(x) long_call_cond:wait() return x * 2 end + +test_run:cmd("setopt delimiter ';'") +for i = 1, N do + fiber.create(function() + fast_call_channel:put(c:call('fast_call', {i, pad})) + end) + fiber.create(function() + long_call_channel:put(c:call('long_call', {i, pad})) + end) +end +test_run:cmd("setopt delimiter ''"); + +x = 0 +for i = 1, N do x = x + fast_call_channel:get() end +x + +long_call_cond:broadcast() + +x = 0 +for i = 1, N do x = x + long_call_channel:get() end +x + +-- +-- Check that a connection does not leak if there is +-- a long CALL in progress when it is closed. +-- +disconnected = false +function on_disconnect() disconnected = true end + +-- Make sure all dangling connections are collected so +-- that on_disconnect trigger isn't called spuriously. +collectgarbage('collect') +fiber.sleep(0) + +box.session.on_disconnect(on_disconnect) == on_disconnect diff --git a/test/box/net.box_collectgarbage_gh-3107.result b/test/box/net.box_collectgarbage_gh-3107.result new file mode 100644 index 000000000..240a472de --- /dev/null +++ b/test/box/net.box_collectgarbage_gh-3107.result @@ -0,0 +1,120 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Ensure the request is garbage collected both if is not used and +-- if is. +-- +gc_test = setmetatable({}, {__mode = 'v'}) +--- +... +gc_test.future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +gc_test.future ~= nil +--- +- true +... +collectgarbage() +--- +- 0 +... +gc_test +--- +- [] +... +finalize_long() +--- +... +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +collectgarbage() +--- +- 0 +... +future ~= nil +--- +- true +... +finalize_long() +--- +... +future:wait_result(1000) +--- +- [1, 2, 3] +... +collectgarbage() +--- +- 0 +... +future ~= nil +--- +- true +... +gc_test.future = future +--- +... +future = nil +--- +... +collectgarbage() +--- +- 0 +... +gc_test +--- +- [] +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box_collectgarbage_gh-3107.test.lua b/test/box/net.box_collectgarbage_gh-3107.test.lua new file mode 100644 index 000000000..cfe333757 --- /dev/null +++ b/test/box/net.box_collectgarbage_gh-3107.test.lua @@ -0,0 +1,44 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Ensure the request is garbage collected both if is not used and +-- if is. +-- +gc_test = setmetatable({}, {__mode = 'v'}) +gc_test.future = c:call('long_function', {1, 2, 3}, {is_async = true}) +gc_test.future ~= nil +collectgarbage() +gc_test +finalize_long() + +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +collectgarbage() +future ~= nil +finalize_long() +future:wait_result(1000) +collectgarbage() +future ~= nil +gc_test.future = future +future = nil +collectgarbage() +gc_test + +c:close() +s:drop() diff --git a/test/box/net.box_connect_triggers.result b/test/box/net.box_connect_triggers.result new file mode 100644 index 000000000..c5b1ef6db --- /dev/null +++ b/test/box/net.box_connect_triggers.result @@ -0,0 +1,82 @@ +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +-- +-- On_connect/disconnect triggers. +-- +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +test_run:cmd('start server connecter') +--- +- true +... +test_run:cmd("set variable connect_to to 'connecter.listen'") +--- +- true +... +conn = net.connect(connect_to, { reconnect_after = 0.1 }) +--- +... +conn.state +--- +- active +... +connected_cnt = 0 +--- +... +disconnected_cnt = 0 +--- +... +function on_connect() connected_cnt = connected_cnt + 1 end +--- +... +function on_disconnect() disconnected_cnt = disconnected_cnt + 1 end +--- +... +conn:on_connect(on_connect) +--- +... +conn:on_disconnect(on_disconnect) +--- +... +test_run:cmd('stop server connecter') +--- +- true +... +test_run:cmd('start server connecter') +--- +- true +... +while conn.state ~= 'active' do fiber.sleep(0.1) end +--- +... +connected_cnt +--- +- 1 +... +old_disconnected_cnt = disconnected_cnt +--- +... +disconnected_cnt >= 1 +--- +- true +... +conn:close() +--- +... +disconnected_cnt == old_disconnected_cnt + 1 +--- +- true +... +test_run:cmd('stop server connecter') +--- +- true +... diff --git a/test/box/net.box_connect_triggers.test.lua b/test/box/net.box_connect_triggers.test.lua new file mode 100644 index 000000000..86794035e --- /dev/null +++ b/test/box/net.box_connect_triggers.test.lua @@ -0,0 +1,27 @@ +fiber = require 'fiber' +test_run = require('test_run').new() +net = require('net.box') + +-- +-- On_connect/disconnect triggers. +-- +test_run:cmd('create server connecter with script = "box/proxy.lua"') +test_run:cmd('start server connecter') +test_run:cmd("set variable connect_to to 'connecter.listen'") +conn = net.connect(connect_to, { reconnect_after = 0.1 }) +conn.state +connected_cnt = 0 +disconnected_cnt = 0 +function on_connect() connected_cnt = connected_cnt + 1 end +function on_disconnect() disconnected_cnt = disconnected_cnt + 1 end +conn:on_connect(on_connect) +conn:on_disconnect(on_disconnect) +test_run:cmd('stop server connecter') +test_run:cmd('start server connecter') +while conn.state ~= 'active' do fiber.sleep(0.1) end +connected_cnt +old_disconnected_cnt = disconnected_cnt +disconnected_cnt >= 1 +conn:close() +disconnected_cnt == old_disconnected_cnt + 1 +test_run:cmd('stop server connecter') diff --git a/test/box/net.box_console_connections_gh-2677.result b/test/box/net.box_console_connections_gh-2677.result new file mode 100644 index 000000000..c9116e5d4 --- /dev/null +++ b/test/box/net.box_console_connections_gh-2677.result @@ -0,0 +1,95 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-2677: netbox supports console connections, that complicates +-- both console and netbox. It was necessary because before a +-- connection is established, a console does not known is it +-- binary or text protocol, and netbox could not be created from +-- existing socket. +-- +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +urilib = require('uri') +--- +... +uri = urilib.parse(tostring(box.cfg.listen)) +--- +... +s, greeting = net.establish_connection(uri.host, uri.service) +--- +... +c = net.wrap(s, greeting, uri.host, uri.service, {reconnect_after = 0.01}) +--- +... +c.state +--- +- active +... +a = 100 +--- +... +function kek(args) return {1, 2, 3, args} end +--- +... +c:eval('a = 200') +--- +... +a +--- +- 200 +... +c:call('kek', {300}) +--- +- [1, 2, 3, 300] +... +s = box.schema.create_space('test') +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'test') +--- +... +pk = s:create_index('pk') +--- +... +c:reload_schema() +--- +... +c.space.test:replace{1} +--- +- [1] +... +c.space.test:get{1} +--- +- [1] +... +c.space.test:delete{1} +--- +- [1] +... +-- +-- Break a connection to test reconnect_after. +-- +_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') +--- +... +while not c:is_connected() do fiber.sleep(0.01) end +--- +... +c:ping() +--- +- true +... +s:drop() +--- +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_console_connections_gh-2677.test.lua b/test/box/net.box_console_connections_gh-2677.test.lua new file mode 100644 index 000000000..c6c9ea846 --- /dev/null +++ b/test/box/net.box_console_connections_gh-2677.test.lua @@ -0,0 +1,39 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-2677: netbox supports console connections, that complicates +-- both console and netbox. It was necessary because before a +-- connection is established, a console does not known is it +-- binary or text protocol, and netbox could not be created from +-- existing socket. +-- +box.schema.user.grant('guest', 'execute', 'universe') +urilib = require('uri') +uri = urilib.parse(tostring(box.cfg.listen)) +s, greeting = net.establish_connection(uri.host, uri.service) +c = net.wrap(s, greeting, uri.host, uri.service, {reconnect_after = 0.01}) +c.state + +a = 100 +function kek(args) return {1, 2, 3, args} end +c:eval('a = 200') +a +c:call('kek', {300}) +s = box.schema.create_space('test') +box.schema.user.grant('guest', 'read,write', 'space', 'test') +pk = s:create_index('pk') +c:reload_schema() +c.space.test:replace{1} +c.space.test:get{1} +c.space.test:delete{1} +-- +-- Break a connection to test reconnect_after. +-- +_ = c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') +while not c:is_connected() do fiber.sleep(0.01) end +c:ping() + +s:drop() +c:close() +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_count_inconsistent_gh-3262.result b/test/box/net.box_count_inconsistent_gh-3262.result new file mode 100644 index 000000000..c77677625 --- /dev/null +++ b/test/box/net.box_count_inconsistent_gh-3262.result @@ -0,0 +1,488 @@ +remote = require 'net.box' +--- +... +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +space = box.schema.space.create('net_box_test_space') +--- +... +index = space:create_index('primary', { type = 'tree' }) +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +cn = remote.connect(box.cfg.listen) +--- +... +cn.space[space.id] ~= nil +--- +- true +... +cn.space.net_box_test_space ~= nil +--- +- true +... +cn.space.net_box_test_space ~= nil +--- +- true +... +cn.space.net_box_test_space.index ~= nil +--- +- true +... +cn.space.net_box_test_space.index.primary ~= nil +--- +- true +... +cn.space.net_box_test_space.index[space.index.primary.id] ~= nil +--- +- true +... +cn.space.net_box_test_space:insert{234, 1,2,3} +--- +- [234, 1, 2, 3] +... +cn.space.net_box_test_space:replace{354, 1,2,4} +--- +- [354, 1, 2, 4] +... +cn.space.net_box_test_space.index.primary:min(354) +--- +- [354, 1, 2, 4] +... +cn.space.net_box_test_space.index.primary:max(234) +--- +- [234, 1, 2, 3] +... +cn.space.net_box_test_space.index.primary:count(354) +--- +- 1 +... +box.schema.user.create('netbox', { password = 'test' }) +--- +... +box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') +--- +... +box.schema.user.grant('netbox', 'execute', 'universe') +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' }) +--- +... +cn.state +--- +- active +... +cn.error +--- +- null +... +cn:ping() +--- +- true +... +function ret_after(to) fiber.sleep(to) return {{to}} end +--- +... +cn:ping({timeout = 1.00}) +--- +- true +... +cn:ping({timeout = 1e-9}) +--- +- false +... +cn:ping() +--- +- true +... +remote_space = cn.space.net_box_test_space +--- +... +remote_pk = remote_space.index.primary +--- +... +remote_space:insert({0}, { timeout = 1.00 }) +--- +- [0] +... +remote_space:insert({1}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_space:insert({2}) +--- +- [2] +... +remote_space:replace({0}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_space:replace({1}) +--- +- [1] +... +remote_space:replace({2}, { timeout = 1.00 }) +--- +- [2] +... +remote_space:upsert({3}, {}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_space:upsert({4}, {}) +--- +... +remote_space:upsert({5}, {}, { timeout = 1.00 }) +--- +... +remote_space:upsert({3}, {}) +--- +... +remote_space:update({3}, {}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_space:update({4}, {}) +--- +- [4] +... +remote_space:update({5}, {}, { timeout = 1.00 }) +--- +- [5] +... +remote_space:update({3}, {}) +--- +- [3] +... +remote_pk:update({5}, {}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:update({4}, {}) +--- +- [4] +... +remote_pk:update({3}, {}, { timeout = 1.00 }) +--- +- [3] +... +remote_pk:update({5}, {}) +--- +- [5] +... +remote_space:get({0}) +--- +- [0] +... +remote_space:get({1}, { timeout = 1.00 }) +--- +- [1] +... +remote_space:get({2}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:get({3}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:get({4}) +--- +- [4] +... +remote_pk:get({5}, { timeout = 1.00 }) +--- +- [5] +... +remote_space:select({2}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_space:select({2}, { timeout = 1.00 }) +--- +- - [2] +... +remote_space:select({2}) +--- +- - [2] +... +remote_pk:select({2}, { timeout = 1.00 }) +--- +- - [2] +... +remote_pk:select({2}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:select({2}) +--- +- - [2] +... +remote_space:select({5}, { timeout = 1.00, iterator = 'LE', limit = 5 }) +--- +- - [5] + - [4] + - [3] + - [2] + - [1] +... +remote_space:select({5}, { iterator = 'LE', limit = 5}) +--- +- - [5] + - [4] + - [3] + - [2] + - [1] +... +remote_space:select({5}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) +--- +- error: Timeout exceeded +... +remote_pk:select({2}, { timeout = 1.00, iterator = 'LE', limit = 5 }) +--- +- - [2] + - [1] + - [0] +... +remote_pk:select({2}, { iterator = 'LE', limit = 5}) +--- +- - [2] + - [1] + - [0] +... +remote_pk:select({2}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) +--- +- error: Timeout exceeded +... +remote_pk:count({2}, { timeout = 1.00}) +--- +- 1 +... +remote_pk:count({2}, { timeout = 1e-9}) +--- +- error: Timeout exceeded +... +remote_pk:count({2}) +--- +- 1 +... +remote_pk:count({2}, { timeout = 1.00, iterator = 'LE' }) +--- +- 3 +... +remote_pk:count({2}, { iterator = 'LE'}) +--- +- 3 +... +remote_pk:count({2}, { timeout = 1e-9, iterator = 'LE' }) +--- +- error: Timeout exceeded +... +remote_pk:min(nil, { timeout = 1.00 }) +--- +- [0] +... +remote_pk:min(nil, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:min(nil) +--- +- [0] +... +remote_pk:min({0}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:min({1}) +--- +- [1] +... +remote_pk:min({2}, { timeout = 1.00 }) +--- +- [2] +... +remote_pk:max(nil) +--- +- [354, 1, 2, 4] +... +remote_pk:max(nil, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:max(nil, { timeout = 1.00 }) +--- +- [354, 1, 2, 4] +... +remote_pk:max({0}, { timeout = 1.00 }) +--- +- [0] +... +remote_pk:max({1}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +remote_pk:max({2}) +--- +- [2] +... +-- +-- gh-3262: index:count() inconsistent results +-- +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function do_count_test(min, it) + local r1 = remote_pk:count(min, {iterator = it} ) + local r2 = box.space.net_box_test_space.index.primary:count(min, {iterator = it} ) + local r3 = remote.self.space.net_box_test_space.index.primary:count(min, {iterator = it} ) + return r1 == r2 and r2 == r3 +end; +--- +... +data = remote_pk:select(); +--- +... +for _, v in pairs(data) do + local itrs = {'GE', 'GT', 'LE', 'LT' } + for _, it in pairs(itrs) do + assert(do_count_test(v[0], it) == true) + end +end; +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +_ = remote_space:delete({0}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +_ = remote_pk:delete({0}, { timeout = 1.00 }) +--- +... +_ = remote_space:delete({1}, { timeout = 1.00 }) +--- +... +_ = remote_pk:delete({1}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +_ = remote_space:delete({2}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +_ = remote_pk:delete({2}) +--- +... +_ = remote_pk:delete({3}) +--- +... +_ = remote_pk:delete({4}) +--- +... +_ = remote_pk:delete({5}) +--- +... +remote_space:get(0) +--- +... +remote_space:get(1) +--- +... +remote_space:get(2) +--- +... +remote_space = nil +--- +... +cn:call('ret_after', {0.01}, { timeout = 1.00 }) +--- +- [[0.01]] +... +cn:call('ret_after', {1.00}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +cn:eval('return ret_after(...)', {0.01}, { timeout = 1.00 }) +--- +- [[0.01]] +... +cn:eval('return ret_after(...)', {1.00}, { timeout = 1e-9 }) +--- +- error: Timeout exceeded +... +-- +-- :timeout() +-- @deprecated since 1.7.4 +-- +cn:timeout(1).space.net_box_test_space.index.primary:select{234} +--- +- - [234, 1, 2, 3] +... +cn:call('ret_after', {.01}) +--- +- [[0.01]] +... +cn:timeout(1):call('ret_after', {.01}) +--- +- [[0.01]] +... +cn:timeout(.01):call('ret_after', {1}) +--- +- error: Timeout exceeded +... +cn = remote:timeout(0.0000000001):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) +--- +... +cn:close() +--- +... +cn = remote:timeout(1):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) +--- +... +remote.self:ping() +--- +- true +... +remote.self.space.net_box_test_space:select{234} +--- +- - [234, 1, 2, 3] +... +remote.self:timeout(123).space.net_box_test_space:select{234} +--- +- - [234, 1, 2, 3] +... +remote.self:is_connected() +--- +- true +... +remote.self:wait_connected() +--- +- true +... +cn:close() +--- +... +-- cleanup database after tests +space:drop() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_count_inconsistent_gh-3262.test.lua b/test/box/net.box_count_inconsistent_gh-3262.test.lua new file mode 100644 index 000000000..e84e85cf3 --- /dev/null +++ b/test/box/net.box_count_inconsistent_gh-3262.test.lua @@ -0,0 +1,182 @@ +remote = require 'net.box' +fiber = require 'fiber' +test_run = require('test_run').new() + +LISTEN = require('uri').parse(box.cfg.listen) +space = box.schema.space.create('net_box_test_space') +index = space:create_index('primary', { type = 'tree' }) + +box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') +box.schema.user.grant('guest', 'execute', 'universe') + +cn = remote.connect(box.cfg.listen) +cn.space[space.id] ~= nil +cn.space.net_box_test_space ~= nil +cn.space.net_box_test_space ~= nil +cn.space.net_box_test_space.index ~= nil +cn.space.net_box_test_space.index.primary ~= nil +cn.space.net_box_test_space.index[space.index.primary.id] ~= nil +cn.space.net_box_test_space:insert{234, 1,2,3} +cn.space.net_box_test_space:replace{354, 1,2,4} +cn.space.net_box_test_space.index.primary:min(354) +cn.space.net_box_test_space.index.primary:max(234) +cn.space.net_box_test_space.index.primary:count(354) + +box.schema.user.create('netbox', { password = 'test' }) +box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') +box.schema.user.grant('netbox', 'execute', 'universe') +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = 'test' }) +cn.state +cn.error +cn:ping() + +function ret_after(to) fiber.sleep(to) return {{to}} end + +cn:ping({timeout = 1.00}) +cn:ping({timeout = 1e-9}) +cn:ping() + +remote_space = cn.space.net_box_test_space +remote_pk = remote_space.index.primary + +remote_space:insert({0}, { timeout = 1.00 }) +remote_space:insert({1}, { timeout = 1e-9 }) +remote_space:insert({2}) + +remote_space:replace({0}, { timeout = 1e-9 }) +remote_space:replace({1}) +remote_space:replace({2}, { timeout = 1.00 }) + +remote_space:upsert({3}, {}, { timeout = 1e-9 }) +remote_space:upsert({4}, {}) +remote_space:upsert({5}, {}, { timeout = 1.00 }) +remote_space:upsert({3}, {}) + +remote_space:update({3}, {}, { timeout = 1e-9 }) +remote_space:update({4}, {}) +remote_space:update({5}, {}, { timeout = 1.00 }) +remote_space:update({3}, {}) + +remote_pk:update({5}, {}, { timeout = 1e-9 }) +remote_pk:update({4}, {}) +remote_pk:update({3}, {}, { timeout = 1.00 }) +remote_pk:update({5}, {}) + +remote_space:get({0}) +remote_space:get({1}, { timeout = 1.00 }) +remote_space:get({2}, { timeout = 1e-9 }) + +remote_pk:get({3}, { timeout = 1e-9 }) +remote_pk:get({4}) +remote_pk:get({5}, { timeout = 1.00 }) + +remote_space:select({2}, { timeout = 1e-9 }) +remote_space:select({2}, { timeout = 1.00 }) +remote_space:select({2}) + +remote_pk:select({2}, { timeout = 1.00 }) +remote_pk:select({2}, { timeout = 1e-9 }) +remote_pk:select({2}) + +remote_space:select({5}, { timeout = 1.00, iterator = 'LE', limit = 5 }) +remote_space:select({5}, { iterator = 'LE', limit = 5}) +remote_space:select({5}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) + +remote_pk:select({2}, { timeout = 1.00, iterator = 'LE', limit = 5 }) +remote_pk:select({2}, { iterator = 'LE', limit = 5}) +remote_pk:select({2}, { timeout = 1e-9, iterator = 'LE', limit = 5 }) + +remote_pk:count({2}, { timeout = 1.00}) +remote_pk:count({2}, { timeout = 1e-9}) +remote_pk:count({2}) + +remote_pk:count({2}, { timeout = 1.00, iterator = 'LE' }) +remote_pk:count({2}, { iterator = 'LE'}) +remote_pk:count({2}, { timeout = 1e-9, iterator = 'LE' }) + +remote_pk:min(nil, { timeout = 1.00 }) +remote_pk:min(nil, { timeout = 1e-9 }) +remote_pk:min(nil) + +remote_pk:min({0}, { timeout = 1e-9 }) +remote_pk:min({1}) +remote_pk:min({2}, { timeout = 1.00 }) + +remote_pk:max(nil) +remote_pk:max(nil, { timeout = 1e-9 }) +remote_pk:max(nil, { timeout = 1.00 }) + +remote_pk:max({0}, { timeout = 1.00 }) +remote_pk:max({1}, { timeout = 1e-9 }) +remote_pk:max({2}) + +-- +-- gh-3262: index:count() inconsistent results +-- +test_run:cmd("setopt delimiter ';'") + +function do_count_test(min, it) + local r1 = remote_pk:count(min, {iterator = it} ) + local r2 = box.space.net_box_test_space.index.primary:count(min, {iterator = it} ) + local r3 = remote.self.space.net_box_test_space.index.primary:count(min, {iterator = it} ) + return r1 == r2 and r2 == r3 +end; + +data = remote_pk:select(); + +for _, v in pairs(data) do + local itrs = {'GE', 'GT', 'LE', 'LT' } + for _, it in pairs(itrs) do + assert(do_count_test(v[0], it) == true) + end +end; + +test_run:cmd("setopt delimiter ''"); + +_ = remote_space:delete({0}, { timeout = 1e-9 }) +_ = remote_pk:delete({0}, { timeout = 1.00 }) +_ = remote_space:delete({1}, { timeout = 1.00 }) +_ = remote_pk:delete({1}, { timeout = 1e-9 }) +_ = remote_space:delete({2}, { timeout = 1e-9 }) +_ = remote_pk:delete({2}) +_ = remote_pk:delete({3}) +_ = remote_pk:delete({4}) +_ = remote_pk:delete({5}) + +remote_space:get(0) +remote_space:get(1) +remote_space:get(2) + +remote_space = nil + +cn:call('ret_after', {0.01}, { timeout = 1.00 }) +cn:call('ret_after', {1.00}, { timeout = 1e-9 }) + +cn:eval('return ret_after(...)', {0.01}, { timeout = 1.00 }) +cn:eval('return ret_after(...)', {1.00}, { timeout = 1e-9 }) + +-- +-- :timeout() +-- @deprecated since 1.7.4 +-- + +cn:timeout(1).space.net_box_test_space.index.primary:select{234} +cn:call('ret_after', {.01}) +cn:timeout(1):call('ret_after', {.01}) +cn:timeout(.01):call('ret_after', {1}) + +cn = remote:timeout(0.0000000001):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) +cn:close() +cn = remote:timeout(1):connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123' }) + +remote.self:ping() +remote.self.space.net_box_test_space:select{234} +remote.self:timeout(123).space.net_box_test_space:select{234} +remote.self:is_connected() +remote.self:wait_connected() + +cn:close() +-- cleanup database after tests +space:drop() + +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_discard_gh-3107.result b/test/box/net.box_discard_gh-3107.result new file mode 100644 index 000000000..3498c9d5a --- /dev/null +++ b/test/box/net.box_discard_gh-3107.result @@ -0,0 +1,119 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +ret = {} +--- +... +count = 0 +--- +... +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +--- +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +while count ~= 10 do fiber.sleep(0.1) end +--- +... +ret +--- +- - &0 [1, 2, 3] + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 +... +-- +-- Test discard. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +future:discard() +--- +... +finalize_long() +--- +... +future:result() +--- +- null +- Response is discarded +... +future:wait_result(100) +--- +- null +- Response is discarded +... +box.schema.func.drop('long_function') +--- +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box_discard_gh-3107.test.lua b/test/box/net.box_discard_gh-3107.test.lua new file mode 100644 index 000000000..71f08a411 --- /dev/null +++ b/test/box/net.box_discard_gh-3107.test.lua @@ -0,0 +1,44 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +ret = {} +count = 0 +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +while count ~= 10 do fiber.sleep(0.1) end +ret + +-- +-- Test discard. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +future:discard() +finalize_long() +future:result() +future:wait_result(100) + +box.schema.func.drop('long_function') + +c:close() +s:drop() diff --git a/test/box/net.box_disconnect_gh-3859.result b/test/box/net.box_disconnect_gh-3859.result new file mode 100644 index 000000000..eae259740 --- /dev/null +++ b/test/box/net.box_disconnect_gh-3859.result @@ -0,0 +1,113 @@ +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +box.schema.func.create('fast_call') +--- +... +box.schema.func.create('long_call') +--- +... +box.schema.func.create('wait_signal') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'fast_call') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_call') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') +--- +... +c = net.connect(box.cfg.listen) +--- +... +disconnected = false +--- +... +function on_disconnect() disconnected = true end +--- +... +-- Make sure all dangling connections are collected so +-- that on_disconnect trigger isn't called spuriously. +collectgarbage('collect') +--- +- 0 +... +fiber.sleep(0) +--- +... +box.session.on_disconnect(on_disconnect) == on_disconnect +--- +- true +... +-- +-- gh-3859: on_disconnect is called only after all requests are +-- processed, but should be called right after disconnect and +-- only once. +-- +ch1 = fiber.channel(1) +--- +... +ch2 = fiber.channel(1) +--- +... +function wait_signal() ch1:put(true) ch2:get() end +--- +... +_ = fiber.create(function() c:call('wait_signal') end) +--- +... +ch1:get() +--- +- true +... +c:close() +--- +... +fiber.sleep(0) +--- +... +while disconnected == false do fiber.sleep(0.01) end +--- +... +disconnected -- true +--- +- true +... +disconnected = nil +--- +... +ch2:put(true) +--- +- true +... +fiber.sleep(0) +--- +... +disconnected -- nil, on_disconnect is not called second time. +--- +- null +... +box.session.on_disconnect(nil, on_disconnect) +--- +... +box.schema.func.drop('long_call') +--- +... +box.schema.func.drop('fast_call') +--- +... +box.schema.func.drop('wait_signal') +--- +... diff --git a/test/box/net.box_disconnect_gh-3859.test.lua b/test/box/net.box_disconnect_gh-3859.test.lua new file mode 100644 index 000000000..e0ec1a8ea --- /dev/null +++ b/test/box/net.box_disconnect_gh-3859.test.lua @@ -0,0 +1,50 @@ +fiber = require 'fiber' +test_run = require('test_run').new() +net = require('net.box') + +test_run:cmd('create server connecter with script = "box/proxy.lua"') + +box.schema.func.create('fast_call') +box.schema.func.create('long_call') +box.schema.func.create('wait_signal') +box.schema.user.grant('guest', 'execute', 'function', 'fast_call') +box.schema.user.grant('guest', 'execute', 'function', 'long_call') +box.schema.user.grant('guest', 'execute', 'function', 'wait_signal') +c = net.connect(box.cfg.listen) + +disconnected = false +function on_disconnect() disconnected = true end + +-- Make sure all dangling connections are collected so +-- that on_disconnect trigger isn't called spuriously. +collectgarbage('collect') +fiber.sleep(0) + +box.session.on_disconnect(on_disconnect) == on_disconnect + +-- +-- gh-3859: on_disconnect is called only after all requests are +-- processed, but should be called right after disconnect and +-- only once. +-- +ch1 = fiber.channel(1) +ch2 = fiber.channel(1) +function wait_signal() ch1:put(true) ch2:get() end +_ = fiber.create(function() c:call('wait_signal') end) +ch1:get() + +c:close() +fiber.sleep(0) +while disconnected == false do fiber.sleep(0.01) end +disconnected -- true +disconnected = nil + +ch2:put(true) +fiber.sleep(0) +disconnected -- nil, on_disconnect is not called second time. + +box.session.on_disconnect(nil, on_disconnect) + +box.schema.func.drop('long_call') +box.schema.func.drop('fast_call') +box.schema.func.drop('wait_signal') diff --git a/test/box/net.box_fiber-async_gh-3107.result b/test/box/net.box_fiber-async_gh-3107.result new file mode 100644 index 000000000..aaaca351a --- /dev/null +++ b/test/box/net.box_fiber-async_gh-3107.result @@ -0,0 +1,115 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Check long connections, multiple wait_result(). +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +future:result() +--- +- null +- Response is not ready +... +future:is_ready() +--- +- false +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +ret = future:wait_result(100) +--- +... +future:is_ready() +--- +- true +... +-- Any timeout is ok - response is received already. +future:wait_result(0) +--- +- [1, 2, 3] +... +future:wait_result(0.01) +--- +- [1, 2, 3] +... +ret +--- +- [1, 2, 3] +... +_, err = pcall(future.wait_result, future, true) +--- +... +err:find('Usage') ~= nil +--- +- true +... +_, err = pcall(future.wait_result, future, '100') +--- +... +err:find('Usage') ~= nil +--- +- true +... +box.schema.func.drop('long_function') +--- +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box_fiber-async_gh-3107.test.lua b/test/box/net.box_fiber-async_gh-3107.test.lua new file mode 100644 index 000000000..d23f368cb --- /dev/null +++ b/test/box/net.box_fiber-async_gh-3107.test.lua @@ -0,0 +1,42 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) +-- +-- Check long connections, multiple wait_result(). +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +future:result() +future:is_ready() +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +ret = future:wait_result(100) +future:is_ready() +-- Any timeout is ok - response is received already. +future:wait_result(0) +future:wait_result(0.01) +ret + +_, err = pcall(future.wait_result, future, true) +err:find('Usage') ~= nil +_, err = pcall(future.wait_result, future, '100') +err:find('Usage') ~= nil + +box.schema.func.drop('long_function') + +c:close() +s:drop() diff --git a/test/box/net.box_field_names_gh-2978.result b/test/box/net.box_field_names_gh-2978.result new file mode 100644 index 000000000..2b6ea9c44 --- /dev/null +++ b/test/box/net.box_field_names_gh-2978.result @@ -0,0 +1,101 @@ +net = require('net.box') +--- +... +-- +-- gh-2978: field names for tuples received from netbox. +-- +_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}}) +--- +... +_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}}) +--- +... +box.space.named:insert({1, 1}) +--- +- [1, 1] +... +box.schema.user.grant('guest', 'read, write, execute', 'space') +--- +... +cn = net.connect(box.cfg.listen) +--- +... +s = cn.space.named +--- +... +s:get{1}.id +--- +- 1 +... +s:get{1}:tomap() +--- +- 1: 1 + 2: 1 + abc: 1 + id: 1 +... +s:insert{2,3}:tomap() +--- +- 1: 2 + 2: 3 + abc: 3 + id: 2 +... +s:replace{2,14}:tomap() +--- +- 1: 2 + 2: 14 + abc: 14 + id: 2 +... +s:update(1, {{'+', 2, 10}}):tomap() +--- +- 1: 1 + 2: 11 + abc: 11 + id: 1 +... +s:select()[1]:tomap() +--- +- 1: 1 + 2: 11 + abc: 11 + id: 1 +... +s:delete({2}):tomap() +--- +- 1: 2 + 2: 14 + abc: 14 + id: 2 +... +-- Check that formats changes after reload. +box.space.named:format({{name = "id2"}, {name="abc2"}}) +--- +... +s:select()[1]:tomap() +--- +- 1: 1 + 2: 11 + abc: 11 + id: 1 +... +cn:reload_schema() +--- +... +s:select()[1]:tomap() +--- +- 1: 1 + 2: 11 + id2: 1 + abc2: 11 +... +cn:close() +--- +... +box.space.named:drop() +--- +... +box.schema.user.revoke('guest', 'read, write, execute', 'space') +--- +... diff --git a/test/box/net.box_field_names_gh-2978.test.lua b/test/box/net.box_field_names_gh-2978.test.lua new file mode 100644 index 000000000..a5dccf16a --- /dev/null +++ b/test/box/net.box_field_names_gh-2978.test.lua @@ -0,0 +1,29 @@ +net = require('net.box') + +-- +-- gh-2978: field names for tuples received from netbox. +-- +_ = box.schema.create_space("named", {format = {{name = "id"}, {name="abc"}}}) +_ = box.space.named:create_index('id', {parts = {{1, 'unsigned'}}}) +box.space.named:insert({1, 1}) +box.schema.user.grant('guest', 'read, write, execute', 'space') +cn = net.connect(box.cfg.listen) + +s = cn.space.named +s:get{1}.id +s:get{1}:tomap() +s:insert{2,3}:tomap() +s:replace{2,14}:tomap() +s:update(1, {{'+', 2, 10}}):tomap() +s:select()[1]:tomap() +s:delete({2}):tomap() + +-- Check that formats changes after reload. +box.space.named:format({{name = "id2"}, {name="abc2"}}) +s:select()[1]:tomap() +cn:reload_schema() +s:select()[1]:tomap() + +cn:close() +box.space.named:drop() +box.schema.user.revoke('guest', 'read, write, execute', 'space') diff --git a/test/box/net.box_get_connection_object.result b/test/box/net.box_get_connection_object.result new file mode 100644 index 000000000..f461477ed --- /dev/null +++ b/test/box/net.box_get_connection_object.result @@ -0,0 +1,40 @@ +net = require('net.box') +--- +... +-- +-- Check that it's possible to get connection object form net.box space +-- +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +--- +... +space ~= nil +--- +- true +... +_ = box.space.test:create_index('primary') +--- +... +box.schema.user.grant('guest','read,write,execute','space', 'test') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:ping() +--- +- true +... +c.space.test ~= nil +--- +- true +... +c.space.test.connection == c +--- +- true +... +box.schema.user.revoke('guest','read,write,execute','space', 'test') +--- +... +c:close() +--- +... diff --git a/test/box/net.box_get_connection_object.test.lua b/test/box/net.box_get_connection_object.test.lua new file mode 100644 index 000000000..71ed110b9 --- /dev/null +++ b/test/box/net.box_get_connection_object.test.lua @@ -0,0 +1,19 @@ +net = require('net.box') + +-- +-- Check that it's possible to get connection object form net.box space +-- + +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +space ~= nil +_ = box.space.test:create_index('primary') +box.schema.user.grant('guest','read,write,execute','space', 'test') + +c = net.connect(box.cfg.listen) + +c:ping() +c.space.test ~= nil + +c.space.test.connection == c +box.schema.user.revoke('guest','read,write,execute','space', 'test') +c:close() diff --git a/test/box/net.box_gibberish_gh-3900.result b/test/box/net.box_gibberish_gh-3900.result new file mode 100644 index 000000000..302c74c9f --- /dev/null +++ b/test/box/net.box_gibberish_gh-3900.result @@ -0,0 +1,31 @@ +test_run = require('test_run').new() +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +-- +-- gh-3900: tarantool can be crashed by sending gibberish to a +-- binary socket +-- +socket = require("socket") +--- +... +sock = socket.tcp_connect(LISTEN.host, LISTEN.service) +--- +... +data = string.fromhex("6783000000000000000000000000000000000000000000800000C8000000000000000000000000000000000000000000FFFF210100373208000000FFFF000055AAEB66486472530D02000000000010A0350001008000001000000000000000000000000000D05700") +--- +... +sock:write(data) +--- +- 104 +... +test_run:wait_log('default', 'ER_INVALID_MSGPACK: Invalid MsgPack %- packet body', nil, 10) +--- +- 'ER_INVALID_MSGPACK: Invalid MsgPack - packet body' +... +sock:close() +--- +- true +... diff --git a/test/box/net.box_gibberish_gh-3900.test.lua b/test/box/net.box_gibberish_gh-3900.test.lua new file mode 100644 index 000000000..7debfd4b3 --- /dev/null +++ b/test/box/net.box_gibberish_gh-3900.test.lua @@ -0,0 +1,13 @@ +test_run = require('test_run').new() +LISTEN = require('uri').parse(box.cfg.listen) + +-- +-- gh-3900: tarantool can be crashed by sending gibberish to a +-- binary socket +-- +socket = require("socket") +sock = socket.tcp_connect(LISTEN.host, LISTEN.service) +data = string.fromhex("6783000000000000000000000000000000000000000000800000C8000000000000000000000000000000000000000000FFFF210100373208000000FFFF000055AAEB66486472530D02000000000010A0350001008000001000000000000000000000000000D05700") +sock:write(data) +test_run:wait_log('default', 'ER_INVALID_MSGPACK: Invalid MsgPack %- packet body', nil, 10) +sock:close() diff --git a/test/box/net.box_huge_data_gh-983.result b/test/box/net.box_huge_data_gh-983.result new file mode 100644 index 000000000..e9b470e28 --- /dev/null +++ b/test/box/net.box_huge_data_gh-983.result @@ -0,0 +1,30 @@ +-- gh-983 selecting a lot of data crashes the server or hangs the +-- connection +-- gh-983 test case: iproto connection selecting a lot of data +_ = box.schema.space.create('test', { temporary = true }) +--- +... +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) +--- +... +data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhh" +--- +... +for i = 0,10000 do box.space.test:insert{i, data1k} end +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +net = require('net.box') +--- +... +c = net:connect(box.cfg.listen) +--- +... +r = c.space.test:select(nil, {limit=5000}) +--- +... +box.space.test:drop() +--- +... diff --git a/test/box/net.box_huge_data_gh-983.test.lua b/test/box/net.box_huge_data_gh-983.test.lua new file mode 100644 index 000000000..93df08834 --- /dev/null +++ b/test/box/net.box_huge_data_gh-983.test.lua @@ -0,0 +1,16 @@ +-- gh-983 selecting a lot of data crashes the server or hangs the +-- connection + +-- gh-983 test case: iproto connection selecting a lot of data +_ = box.schema.space.create('test', { temporary = true }) +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) + +data1k = "aaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhhaaaabbbbccccddddeeeeffffgggghhhh" + +for i = 0,10000 do box.space.test:insert{i, data1k} end + +box.schema.user.grant('guest', 'read', 'space', 'test') +net = require('net.box') +c = net:connect(box.cfg.listen) +r = c.space.test:select(nil, {limit=5000}) +box.space.test:drop() diff --git a/test/box/net.box_incompatible_index-gh-1729.result b/test/box/net.box_incompatible_index-gh-1729.result new file mode 100644 index 000000000..1d9fa542e --- /dev/null +++ b/test/box/net.box_incompatible_index-gh-1729.result @@ -0,0 +1,99 @@ +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") +--- +- true +... +_ = box.schema.space.create('test') +--- +... +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) +--- +... +_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) +--- +... +_ = box.space.test:insert{1, 2, "string"} +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'test') +--- +... +c = net:connect(box.cfg.listen) +--- +... +-- gh-1729 net.box index metadata incompatible with local metadata +c.space.test.index.primary.parts +--- +- - type: unsigned + is_nullable: false + fieldno: 1 +... +c.space.test.index.covering.parts +--- +- - type: unsigned + is_nullable: false + fieldno: 1 + - type: string + is_nullable: false + fieldno: 3 + - type: unsigned + is_nullable: false + fieldno: 2 +... +box.space.test:drop() +--- +... +-- CALL vs CALL_16 in connect options +function echo(...) return ... end +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:call('echo', {42}) +--- +- 42 +... +c:eval('return echo(...)', {42}) +--- +- 42 +... +-- invalid arguments +c:call('echo', 42) +--- +- error: 'builtin/box/net_box.lua..."]:: Use remote:call(func_name, {arg1, arg2, ...}, + opts) instead of remote:call(func_name, arg1, arg2, ...)' +... +c:eval('return echo(...)', 42) +--- +- error: 'builtin/box/net_box.lua..."]:: Use remote:eval(expression, {arg1, arg2, ...}, + opts) instead of remote:eval(expression, arg1, arg2, ...)' +... +c:close() +--- +... +c = net.connect(box.cfg.listen, {call_16 = true}) +--- +... +c:call('echo', 42) +--- +- - [42] +... +c:eval('return echo(...)', 42) +--- +- 42 +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_incompatible_index-gh-1729.test.lua b/test/box/net.box_incompatible_index-gh-1729.test.lua new file mode 100644 index 000000000..2d25b9017 --- /dev/null +++ b/test/box/net.box_incompatible_index-gh-1729.test.lua @@ -0,0 +1,33 @@ +test_run = require('test_run').new() +net = require('net.box') + +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") + +_ = box.schema.space.create('test') +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) +_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) +_ = box.space.test:insert{1, 2, "string"} +box.schema.user.grant('guest', 'read,write', 'space', 'test') +c = net:connect(box.cfg.listen) + +-- gh-1729 net.box index metadata incompatible with local metadata +c.space.test.index.primary.parts +c.space.test.index.covering.parts + +box.space.test:drop() + +-- CALL vs CALL_16 in connect options +function echo(...) return ... end +box.schema.user.grant('guest', 'execute', 'universe') +c = net.connect(box.cfg.listen) +c:call('echo', {42}) +c:eval('return echo(...)', {42}) +-- invalid arguments +c:call('echo', 42) +c:eval('return echo(...)', 42) +c:close() +c = net.connect(box.cfg.listen, {call_16 = true}) +c:call('echo', 42) +c:eval('return echo(...)', 42) +c:close() +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_incorrect_iterator_gh-841.result b/test/box/net.box_incorrect_iterator_gh-841.result new file mode 100644 index 000000000..4bdd1afa3 --- /dev/null +++ b/test/box/net.box_incorrect_iterator_gh-841.result @@ -0,0 +1,497 @@ +remote = require 'net.box' +--- +... +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") +--- +- true +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +function x_select(cn, space_id, index_id, iterator, offset, limit, key, opts) + local ret = cn:_request('select', opts, nil, space_id, index_id, iterator, + offset, limit, key) + return ret +end +function x_fatal(cn) cn._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') end +test_run:cmd("setopt delimiter ''"); +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +space = box.schema.space.create('net_box_test_space') +--- +... +index = space:create_index('primary', { type = 'tree' }) +--- +... +function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +cn = remote.connect(box.cfg.listen) +--- +... +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0xFFFFFFFF, 123) +--- +- [] +... +space:insert{123, 345} +--- +- [123, 345] +... +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0, 123) +--- +- [] +... +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 1, 123) +--- +- - [123, 345] +... +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 1, 1, 123) +--- +- [] +... +cn.space[space.id] ~= nil +--- +- true +... +cn.space.net_box_test_space ~= nil +--- +- true +... +cn.space.net_box_test_space ~= nil +--- +- true +... +cn.space.net_box_test_space.index ~= nil +--- +- true +... +cn.space.net_box_test_space.index.primary ~= nil +--- +- true +... +cn.space.net_box_test_space.index[space.index.primary.id] ~= nil +--- +- true +... +cn.space.net_box_test_space.index.primary:select(123) +--- +- - [123, 345] +... +cn.space.net_box_test_space.index.primary:select(123, { limit = 0 }) +--- +- [] +... +cn.space.net_box_test_space.index.primary:select(nil, { limit = 1, }) +--- +- - [123, 345] +... +cn.space.net_box_test_space:insert{234, 1,2,3} +--- +- [234, 1, 2, 3] +... +cn.space.net_box_test_space:insert{234, 1,2,3} +--- +- error: Duplicate key exists in unique index 'primary' in space 'net_box_test_space' +... +cn.space.net_box_test_space.insert{234, 1,2,3} +--- +- error: 'builtin/box/schema.lua..."]:: Use space:insert(...) instead of space.insert(...)' +... +cn.space.net_box_test_space:replace{354, 1,2,3} +--- +- [354, 1, 2, 3] +... +cn.space.net_box_test_space:replace{354, 1,2,4} +--- +- [354, 1, 2, 4] +... +cn.space.net_box_test_space:select{123} +--- +- - [123, 345] +... +space:select({123}, { iterator = 'GE' }) +--- +- - [123, 345] + - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn.space.net_box_test_space:select({123}, { iterator = 'GE' }) +--- +- - [123, 345] + - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn.space.net_box_test_space:select({123}, { iterator = 'GT' }) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1 }) +--- +- - [234, 1, 2, 3] +... +cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1, offset = 1 }) +--- +- - [354, 1, 2, 4] +... +cn.space.net_box_test_space:select{123} +--- +- - [123, 345] +... +cn.space.net_box_test_space:update({123}, { { '+', 2, 1 } }) +--- +- [123, 346] +... +cn.space.net_box_test_space:update(123, { { '+', 2, 1 } }) +--- +- [123, 347] +... +cn.space.net_box_test_space:select{123} +--- +- - [123, 347] +... +cn.space.net_box_test_space:insert(cn.space.net_box_test_space:get{123}:update{ { '=', 1, 2 } }) +--- +- [2, 347] +... +cn.space.net_box_test_space:delete{123} +--- +- [123, 347] +... +cn.space.net_box_test_space:select{2} +--- +- - [2, 347] +... +cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) +--- +- - [2, 347] +... +cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) +--- +... +cn.space.net_box_test_space:delete{1} +--- +... +cn.space.net_box_test_space:delete{2} +--- +- [2, 347] +... +cn.space.net_box_test_space:delete{2} +--- +... +-- test one-based indexing in splice operation (see update.test.lua) +cn.space.net_box_test_space:replace({10, 'abcde'}) +--- +- [10, 'abcde'] +... +cn.space.net_box_test_space:update(10, {{':', 2, 0, 0, '!'}}) +--- +- error: 'SPLICE error on field 2: offset is out of bound' +... +cn.space.net_box_test_space:update(10, {{':', 2, 1, 0, '('}}) +--- +- [10, '(abcde'] +... +cn.space.net_box_test_space:update(10, {{':', 2, 2, 0, '({'}}) +--- +- [10, '(({abcde'] +... +cn.space.net_box_test_space:update(10, {{':', 2, -1, 0, ')'}}) +--- +- [10, '(({abcde)'] +... +cn.space.net_box_test_space:update(10, {{':', 2, -2, 0, '})'}}) +--- +- [10, '(({abcde}))'] +... +cn.space.net_box_test_space:delete{10} +--- +- [10, '(({abcde}))'] +... +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +-- gh-841: net.box uses incorrect iterator type for select with no arguments +cn.space.net_box_test_space:select() +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn.space.net_box_test_space.index.primary:min() +--- +- [234, 1, 2, 3] +... +cn.space.net_box_test_space.index.primary:min(354) +--- +- [354, 1, 2, 4] +... +cn.space.net_box_test_space.index.primary:max() +--- +- [354, 1, 2, 4] +... +cn.space.net_box_test_space.index.primary:max(234) +--- +- [234, 1, 2, 3] +... +cn.space.net_box_test_space.index.primary:count() +--- +- 2 +... +cn.space.net_box_test_space.index.primary:count(354) +--- +- 1 +... +cn.space.net_box_test_space:get(354) +--- +- [354, 1, 2, 4] +... +-- reconnects after errors +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +box.schema.func.create('test_foo') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'test_foo') +--- +... +-- -- 1. no reconnect +x_fatal(cn) +--- +... +cn.state +--- +- error +... +cn:ping() +--- +- false +... +cn:call('test_foo') +--- +- error: Peer closed +... +cn:wait_state('active') +--- +- false +... +-- -- 2 reconnect +cn = remote.connect(LISTEN.host, LISTEN.service, { reconnect_after = .1 }) +--- +... +cn.space ~= nil +--- +- true +... +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +x_fatal(cn) +--- +... +cn:wait_connected() +--- +- true +... +cn:wait_state('active') +--- +- true +... +cn:wait_state({active=true}) +--- +- true +... +cn:ping() +--- +- true +... +cn.state +--- +- active +... +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +x_fatal(cn) +--- +... +x_select(cn, space.id, 0, box.index.ALL, 0, 0xFFFFFFFF, {}) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn.state +--- +- active +... +cn:ping() +--- +- true +... +-- -- dot-new-method +cn1 = remote.new(LISTEN.host, LISTEN.service) +--- +... +x_select(cn1, space.id, 0, box.index.ALL, 0, 0xFFFFFFF, {}) +--- +- - [234, 1, 2, 3] + - [354, 1, 2, 4] +... +cn1:close() +--- +... +-- -- error while waiting for response +type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end)) +--- +- userdata +... +function pause() fiber.sleep(10) return true end +--- +... +box.schema.func.create('pause') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'pause') +--- +... +cn:call('pause') +--- +- error: Peer closed +... +cn:call('test_foo', {'a', 'b', 'c'}) +--- +- [[{'a': 1}], [{'b': 2}], 'c'] +... +box.schema.func.drop('pause') +--- +... +-- call +remote.self:call('test_foo', {'a', 'b', 'c'}) +--- +- - - a: 1 + - - b: 2 + - c +... +cn:call('test_foo', {'a', 'b', 'c'}) +--- +- [[{'a': 1}], [{'b': 2}], 'c'] +... +box.schema.func.drop('test_foo') +--- +... +box.schema.func.create('long_rep') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_rep') +--- +... +-- long replies +function long_rep() return { 1, string.rep('a', 5000) } end +--- +... +res = cn:call('long_rep') +--- +... +res[1] == 1 +--- +- true +... +res[2] == string.rep('a', 5000) +--- +- true +... +function long_rep() return { 1, string.rep('a', 50000) } end +--- +... +res = cn:call('long_rep') +--- +... +res[1] == 1 +--- +- true +... +res[2] == string.rep('a', 50000) +--- +- true +... +box.schema.func.drop('long_rep') +--- +... +-- a.b.c.d +u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E' +--- +... +X = {} +--- +... +X.X = X +--- +... +function X.fn(x,y) return y or x end +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +cn:close() +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service) +--- +... +cn:call('X.fn', {u}) +--- +- 84F7BCFA-079C-46CC-98B4-F0C821BE833E +... +cn:call('X.X.X.X.X.X.X.fn', {u}) +--- +- 84F7BCFA-079C-46CC-98B4-F0C821BE833E +... +cn:call('X.X.X.X:fn', {u}) +--- +- 84F7BCFA-079C-46CC-98B4-F0C821BE833E +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +cn:close() +--- +... +-- auth +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123', wait_connected = true }) +--- +... +cn:is_connected() +--- +- false +... +cn.error +--- +- User 'netbox' is not found +... +cn.state +--- +- error +... diff --git a/test/box/net.box_incorrect_iterator_gh-841.test.lua b/test/box/net.box_incorrect_iterator_gh-841.test.lua new file mode 100644 index 000000000..cd431a57a --- /dev/null +++ b/test/box/net.box_incorrect_iterator_gh-841.test.lua @@ -0,0 +1,182 @@ +remote = require 'net.box' +fiber = require 'fiber' +test_run = require('test_run').new() +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") + +test_run:cmd("setopt delimiter ';'") +function x_select(cn, space_id, index_id, iterator, offset, limit, key, opts) + local ret = cn:_request('select', opts, nil, space_id, index_id, iterator, + offset, limit, key) + return ret +end +function x_fatal(cn) cn._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') end +test_run:cmd("setopt delimiter ''"); + +LISTEN = require('uri').parse(box.cfg.listen) +space = box.schema.space.create('net_box_test_space') +index = space:create_index('primary', { type = 'tree' }) + +function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end + +box.schema.user.grant('guest', 'read,write', 'space', 'net_box_test_space') +box.schema.user.grant('guest', 'execute', 'universe') + +cn = remote.connect(box.cfg.listen) + +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0xFFFFFFFF, 123) +space:insert{123, 345} +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 0, 123) +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 0, 1, 123) +x_select(cn, space.id, space.index.primary.id, box.index.EQ, 1, 1, 123) + +cn.space[space.id] ~= nil +cn.space.net_box_test_space ~= nil +cn.space.net_box_test_space ~= nil +cn.space.net_box_test_space.index ~= nil +cn.space.net_box_test_space.index.primary ~= nil +cn.space.net_box_test_space.index[space.index.primary.id] ~= nil + + +cn.space.net_box_test_space.index.primary:select(123) +cn.space.net_box_test_space.index.primary:select(123, { limit = 0 }) +cn.space.net_box_test_space.index.primary:select(nil, { limit = 1, }) +cn.space.net_box_test_space:insert{234, 1,2,3} +cn.space.net_box_test_space:insert{234, 1,2,3} +cn.space.net_box_test_space.insert{234, 1,2,3} + +cn.space.net_box_test_space:replace{354, 1,2,3} +cn.space.net_box_test_space:replace{354, 1,2,4} + +cn.space.net_box_test_space:select{123} +space:select({123}, { iterator = 'GE' }) +cn.space.net_box_test_space:select({123}, { iterator = 'GE' }) +cn.space.net_box_test_space:select({123}, { iterator = 'GT' }) +cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1 }) +cn.space.net_box_test_space:select({123}, { iterator = 'GT', limit = 1, offset = 1 }) + +cn.space.net_box_test_space:select{123} +cn.space.net_box_test_space:update({123}, { { '+', 2, 1 } }) +cn.space.net_box_test_space:update(123, { { '+', 2, 1 } }) +cn.space.net_box_test_space:select{123} + +cn.space.net_box_test_space:insert(cn.space.net_box_test_space:get{123}:update{ { '=', 1, 2 } }) +cn.space.net_box_test_space:delete{123} +cn.space.net_box_test_space:select{2} +cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) + +cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) + +cn.space.net_box_test_space:delete{1} +cn.space.net_box_test_space:delete{2} +cn.space.net_box_test_space:delete{2} + +-- test one-based indexing in splice operation (see update.test.lua) +cn.space.net_box_test_space:replace({10, 'abcde'}) +cn.space.net_box_test_space:update(10, {{':', 2, 0, 0, '!'}}) +cn.space.net_box_test_space:update(10, {{':', 2, 1, 0, '('}}) +cn.space.net_box_test_space:update(10, {{':', 2, 2, 0, '({'}}) +cn.space.net_box_test_space:update(10, {{':', 2, -1, 0, ')'}}) +cn.space.net_box_test_space:update(10, {{':', 2, -2, 0, '})'}}) +cn.space.net_box_test_space:delete{10} + +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) +-- gh-841: net.box uses incorrect iterator type for select with no arguments +cn.space.net_box_test_space:select() + +cn.space.net_box_test_space.index.primary:min() +cn.space.net_box_test_space.index.primary:min(354) +cn.space.net_box_test_space.index.primary:max() +cn.space.net_box_test_space.index.primary:max(234) +cn.space.net_box_test_space.index.primary:count() +cn.space.net_box_test_space.index.primary:count(354) + +cn.space.net_box_test_space:get(354) + +-- reconnects after errors + +box.schema.user.revoke('guest', 'execute', 'universe') +box.schema.func.create('test_foo') +box.schema.user.grant('guest', 'execute', 'function', 'test_foo') + +-- -- 1. no reconnect +x_fatal(cn) +cn.state +cn:ping() +cn:call('test_foo') +cn:wait_state('active') + +-- -- 2 reconnect +cn = remote.connect(LISTEN.host, LISTEN.service, { reconnect_after = .1 }) +cn.space ~= nil + +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) +x_fatal(cn) +cn:wait_connected() +cn:wait_state('active') +cn:wait_state({active=true}) +cn:ping() +cn.state +cn.space.net_box_test_space:select({}, { iterator = 'ALL' }) + +x_fatal(cn) +x_select(cn, space.id, 0, box.index.ALL, 0, 0xFFFFFFFF, {}) + +cn.state +cn:ping() + +-- -- dot-new-method + +cn1 = remote.new(LISTEN.host, LISTEN.service) +x_select(cn1, space.id, 0, box.index.ALL, 0, 0xFFFFFFF, {}) +cn1:close() +-- -- error while waiting for response +type(fiber.create(function() fiber.sleep(.5) x_fatal(cn) end)) +function pause() fiber.sleep(10) return true end + +box.schema.func.create('pause') +box.schema.user.grant('guest', 'execute', 'function', 'pause') +cn:call('pause') +cn:call('test_foo', {'a', 'b', 'c'}) +box.schema.func.drop('pause') + +-- call +remote.self:call('test_foo', {'a', 'b', 'c'}) +cn:call('test_foo', {'a', 'b', 'c'}) +box.schema.func.drop('test_foo') + +box.schema.func.create('long_rep') +box.schema.user.grant('guest', 'execute', 'function', 'long_rep') + +-- long replies +function long_rep() return { 1, string.rep('a', 5000) } end +res = cn:call('long_rep') +res[1] == 1 +res[2] == string.rep('a', 5000) + +function long_rep() return { 1, string.rep('a', 50000) } end +res = cn:call('long_rep') +res[1] == 1 +res[2] == string.rep('a', 50000) + +box.schema.func.drop('long_rep') + +-- a.b.c.d +u = '84F7BCFA-079C-46CC-98B4-F0C821BE833E' +X = {} +X.X = X +function X.fn(x,y) return y or x end +box.schema.user.grant('guest', 'execute', 'universe') +cn:close() +cn = remote.connect(LISTEN.host, LISTEN.service) +cn:call('X.fn', {u}) +cn:call('X.X.X.X.X.X.X.fn', {u}) +cn:call('X.X.X.X:fn', {u}) +box.schema.user.revoke('guest', 'execute', 'universe') +cn:close() + +-- auth + +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'netbox', password = '123', wait_connected = true }) +cn:is_connected() +cn.error +cn.state diff --git a/test/box/net.box_index_unique_flag_gh-4091.result b/test/box/net.box_index_unique_flag_gh-4091.result new file mode 100644 index 000000000..a72c32c74 --- /dev/null +++ b/test/box/net.box_index_unique_flag_gh-4091.result @@ -0,0 +1,28 @@ +net = require('net.box') +--- +... +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +--- +... +_ = box.space.test:create_index('primary') +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +c = net.connect(box.cfg.listen) +--- +... +-- +-- gh-4091: index unique flag is always false. +-- +c.space.test.index.primary.unique +--- +- true +... +c:close() +--- +... +space:drop() +--- +... diff --git a/test/box/net.box_index_unique_flag_gh-4091.test.lua b/test/box/net.box_index_unique_flag_gh-4091.test.lua new file mode 100644 index 000000000..7027b1e33 --- /dev/null +++ b/test/box/net.box_index_unique_flag_gh-4091.test.lua @@ -0,0 +1,15 @@ +net = require('net.box') + +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +_ = box.space.test:create_index('primary') +box.schema.user.grant('guest', 'read', 'space', 'test') + +c = net.connect(box.cfg.listen) + +-- +-- gh-4091: index unique flag is always false. +-- +c.space.test.index.primary.unique + +c:close() +space:drop() diff --git a/test/box/net.box_iproto_hangs_gh-3464.result b/test/box/net.box_iproto_hangs_gh-3464.result new file mode 100644 index 000000000..d425bf78c --- /dev/null +++ b/test/box/net.box_iproto_hangs_gh-3464.result @@ -0,0 +1,31 @@ +msgpack = require 'msgpack' +--- +... +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +-- +-- gh-3464: iproto hangs in 100% CPU when too big packet size +-- is received due to size_t overflow. +-- +c = net:connect(box.cfg.listen) +--- +... +data = msgpack.encode(18400000000000000000)..'aaaaaaa' +--- +... +c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, data) +--- +- null +- Peer closed +... +c:close() +--- +... +test_run:grep_log('default', 'too big packet size in the header') ~= nil +--- +- true +... diff --git a/test/box/net.box_iproto_hangs_gh-3464.test.lua b/test/box/net.box_iproto_hangs_gh-3464.test.lua new file mode 100644 index 000000000..77551e415 --- /dev/null +++ b/test/box/net.box_iproto_hangs_gh-3464.test.lua @@ -0,0 +1,13 @@ +msgpack = require 'msgpack' +test_run = require('test_run').new() +net = require('net.box') + +-- +-- gh-3464: iproto hangs in 100% CPU when too big packet size +-- is received due to size_t overflow. +-- +c = net:connect(box.cfg.listen) +data = msgpack.encode(18400000000000000000)..'aaaaaaa' +c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, data) +c:close() +test_run:grep_log('default', 'too big packet size in the header') ~= nil diff --git a/test/box/net.box_is_nullable_gh-3256.result b/test/box/net.box_is_nullable_gh-3256.result new file mode 100644 index 000000000..5d6dc4b94 --- /dev/null +++ b/test/box/net.box_is_nullable_gh-3256.result @@ -0,0 +1,97 @@ +net = require('net.box') +--- +... +-- +-- gh-3256 net.box is_nullable and collation options output +-- +space = box.schema.create_space('test') +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +_ = space:create_index('pk') +--- +... +_ = space:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}}) +--- +... +c = net:connect(box.cfg.listen) +--- +... +c.space.test.index.sk.parts +--- +- - type: unsigned + is_nullable: true + fieldno: 2 +... +space:drop() +--- +... +space = box.schema.create_space('test') +--- +... +c:close() +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +c = net:connect(box.cfg.listen) +--- +... +box.internal.collation.create('test', 'ICU', 'ru-RU') +--- +... +collation_id = box.internal.collation.id_by_name('test') +--- +... +_ = space:create_index('sk', { type = 'tree', parts = {{1, 'str', collation = 'test'}}, unique = true }) +--- +... +c:reload_schema() +--- +... +parts = c.space.test.index.sk.parts +--- +... +#parts == 1 +--- +- true +... +parts[1].fieldno == 1 +--- +- true +... +parts[1].type == 'string' +--- +- true +... +parts[1].is_nullable == false +--- +- true +... +if _TARANTOOL >= '2.2.1' then \ + return parts[1].collation == 'test' \ +else \ + return parts[1].collation_id == collation_id \ +end +--- +- true +... +c:close() +--- +... +box.internal.collation.drop('test') +--- +... +space:drop() +--- +... +c.state +--- +- closed +... +c = nil +--- +... diff --git a/test/box/net.box_is_nullable_gh-3256.test.lua b/test/box/net.box_is_nullable_gh-3256.test.lua new file mode 100644 index 000000000..3c5ee3971 --- /dev/null +++ b/test/box/net.box_is_nullable_gh-3256.test.lua @@ -0,0 +1,36 @@ +net = require('net.box') + +-- +-- gh-3256 net.box is_nullable and collation options output +-- +space = box.schema.create_space('test') +box.schema.user.grant('guest', 'read', 'space', 'test') +_ = space:create_index('pk') +_ = space:create_index('sk', {parts = {{2, 'unsigned', is_nullable = true}}}) +c = net:connect(box.cfg.listen) +c.space.test.index.sk.parts +space:drop() + +space = box.schema.create_space('test') +c:close() +box.schema.user.grant('guest', 'read', 'space', 'test') +c = net:connect(box.cfg.listen) +box.internal.collation.create('test', 'ICU', 'ru-RU') +collation_id = box.internal.collation.id_by_name('test') +_ = space:create_index('sk', { type = 'tree', parts = {{1, 'str', collation = 'test'}}, unique = true }) +c:reload_schema() +parts = c.space.test.index.sk.parts +#parts == 1 +parts[1].fieldno == 1 +parts[1].type == 'string' +parts[1].is_nullable == false +if _TARANTOOL >= '2.2.1' then \ + return parts[1].collation == 'test' \ +else \ + return parts[1].collation_id == collation_id \ +end +c:close() +box.internal.collation.drop('test') +space:drop() +c.state +c = nil diff --git a/test/box/net.box_leaks_gh-3629.result b/test/box/net.box_leaks_gh-3629.result new file mode 100644 index 000000000..4c6688bf2 --- /dev/null +++ b/test/box/net.box_leaks_gh-3629.result @@ -0,0 +1,51 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3629: netbox leaks when a connection is closed deliberately +-- and it has non-finished requests. +-- +ready = false +--- +... +ok = nil +--- +... +err = nil +--- +... +c = net:connect(box.cfg.listen) +--- +... +function do_long() while not ready do fiber.sleep(0.01) end end +--- +... +box.schema.func.create('do_long') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'do_long') +--- +... +f = fiber.create(function() ok, err = pcall(c.call, c, 'do_long') end) +--- +... +while f:status() ~= 'suspended' do fiber.sleep(0.01) end +--- +... +c:close() +--- +... +ready = true +--- +... +while not err do fiber.sleep(0.01) end +--- +... +ok, err +--- +- false +- Connection closed +... diff --git a/test/box/net.box_leaks_gh-3629.test.lua b/test/box/net.box_leaks_gh-3629.test.lua new file mode 100644 index 000000000..03b5a2327 --- /dev/null +++ b/test/box/net.box_leaks_gh-3629.test.lua @@ -0,0 +1,20 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3629: netbox leaks when a connection is closed deliberately +-- and it has non-finished requests. +-- +ready = false +ok = nil +err = nil +c = net:connect(box.cfg.listen) +function do_long() while not ready do fiber.sleep(0.01) end end +box.schema.func.create('do_long') +box.schema.user.grant('guest', 'execute', 'function', 'do_long') +f = fiber.create(function() ok, err = pcall(c.call, c, 'do_long') end) +while f:status() ~= 'suspended' do fiber.sleep(0.01) end +c:close() +ready = true +while not err do fiber.sleep(0.01) end +ok, err diff --git a/test/box/net.box_log_corrupted_rows_gh-4040.result b/test/box/net.box_log_corrupted_rows_gh-4040.result new file mode 100644 index 000000000..603de0f13 --- /dev/null +++ b/test/box/net.box_log_corrupted_rows_gh-4040.result @@ -0,0 +1,72 @@ +test_run = require('test_run').new() +--- +... +socket = require('socket'); +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +-- +-- related to gh-4040: log corrupted rows +-- +log_level = box.cfg.log_level +--- +... +box.cfg{log_level=6} +--- +... +sock = socket.tcp_connect(LISTEN.host, LISTEN.service) +--- +... +sock:read(9) +--- +- Tarantool +... +-- we need to have a packet with correctly encoded length, +-- so that it bypasses iproto length check, but cannot be +-- decoded in xrow_header_decode +-- 0x3C = 60, sha1 digest is 20 bytes long +data = string.fromhex('3C'..string.rep(require('digest').sha1_hex('bcde'), 3)) +--- +... +sock:write(data) +--- +- 61 +... +sock:close() +--- +- true +... +test_run:wait_log('default', 'Got a corrupted row.*', nil, 10) +--- +- 'Got a corrupted row:' +... +test_run:wait_log('default', '00000000:.*', nil, 10) +--- +- '00000000: A3 02 D6 5A E4 D9 E7 68 A1 53 8D 53 60 5F 20 3F ' +... +test_run:wait_log('default', '00000010:.*', nil, 10) +--- +- '00000010: D8 E2 D6 E2 A3 02 D6 5A E4 D9 E7 68 A1 53 8D 53 ' +... +test_run:wait_log('default', '00000020:.*', nil, 10) +--- +- '00000020: 60 5F 20 3F D8 E2 D6 E2 A3 02 D6 5A E4 D9 E7 68 ' +... +test_run:wait_log('default', '00000030:.*', nil, 10) +--- +- '00000030: A1 53 8D 53 60 5F 20 3F D8 E2 D6 E2 ' +... +-- we expect nothing below, so don't wait +test_run:grep_log('default', '00000040:.*') +--- +- null +... +box.cfg{log_level=log_level} +--- +... diff --git a/test/box/net.box_log_corrupted_rows_gh-4040.test.lua b/test/box/net.box_log_corrupted_rows_gh-4040.test.lua new file mode 100644 index 000000000..a30b4a254 --- /dev/null +++ b/test/box/net.box_log_corrupted_rows_gh-4040.test.lua @@ -0,0 +1,31 @@ +test_run = require('test_run').new() +socket = require('socket'); + +LISTEN = require('uri').parse(box.cfg.listen) + +test_run:cmd('create server connecter with script = "box/proxy.lua"') + +-- +-- related to gh-4040: log corrupted rows +-- +log_level = box.cfg.log_level +box.cfg{log_level=6} +sock = socket.tcp_connect(LISTEN.host, LISTEN.service) +sock:read(9) +-- we need to have a packet with correctly encoded length, +-- so that it bypasses iproto length check, but cannot be +-- decoded in xrow_header_decode +-- 0x3C = 60, sha1 digest is 20 bytes long +data = string.fromhex('3C'..string.rep(require('digest').sha1_hex('bcde'), 3)) +sock:write(data) +sock:close() + +test_run:wait_log('default', 'Got a corrupted row.*', nil, 10) +test_run:wait_log('default', '00000000:.*', nil, 10) +test_run:wait_log('default', '00000010:.*', nil, 10) +test_run:wait_log('default', '00000020:.*', nil, 10) +test_run:wait_log('default', '00000030:.*', nil, 10) +-- we expect nothing below, so don't wait +test_run:grep_log('default', '00000040:.*') + +box.cfg{log_level=log_level} diff --git a/test/box/net.box_long-poll_input_gh-3400.result b/test/box/net.box_long-poll_input_gh-3400.result new file mode 100644 index 000000000..062bd563a --- /dev/null +++ b/test/box/net.box_long-poll_input_gh-3400.result @@ -0,0 +1,35 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3400: long-poll input discard must not touch event loop of +-- a closed connection. +-- +function long() fiber.yield() return 100 end +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:ping() +--- +- true +... +-- Create batch of two requests. First request is sent to TX +-- thread, second one terminates connection. The preceeding +-- request discards input, and this operation must not trigger +-- new attempts to read any data - the connection is closed +-- already. +-- +f = fiber.create(c._transport.perform_request, nil, nil, false, 'call_17', nil, nil, nil, 'long', {}) c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') +--- +... +while f:status() ~= 'dead' do fiber.sleep(0.01) end +--- +... +c:close() +--- +... diff --git a/test/box/net.box_long-poll_input_gh-3400.test.lua b/test/box/net.box_long-poll_input_gh-3400.test.lua new file mode 100644 index 000000000..bc9db1e69 --- /dev/null +++ b/test/box/net.box_long-poll_input_gh-3400.test.lua @@ -0,0 +1,19 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3400: long-poll input discard must not touch event loop of +-- a closed connection. +-- +function long() fiber.yield() return 100 end +c = net.connect(box.cfg.listen) +c:ping() +-- Create batch of two requests. First request is sent to TX +-- thread, second one terminates connection. The preceeding +-- request discards input, and this operation must not trigger +-- new attempts to read any data - the connection is closed +-- already. +-- +f = fiber.create(c._transport.perform_request, nil, nil, false, 'call_17', nil, nil, nil, 'long', {}) c._transport.perform_request(nil, nil, false, 'inject', nil, nil, nil, '\x80') +while f:status() ~= 'dead' do fiber.sleep(0.01) end +c:close() diff --git a/test/box/net.box_methods_gh-3107.result b/test/box/net.box_methods_gh-3107.result new file mode 100644 index 000000000..8ff69ebd6 --- /dev/null +++ b/test/box/net.box_methods_gh-3107.result @@ -0,0 +1,277 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +ret = {} +--- +... +count = 0 +--- +... +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +--- +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +while count ~= 10 do fiber.sleep(0.1) end +--- +... +ret +--- +- - &0 [1, 2, 3] + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 +... +-- +-- Test space methods. +-- +c:close() +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'test') +--- +... +c = net:connect(box.cfg.listen) +--- +... +future = c.space.test:select({1}, {is_async = true}) +--- +... +ret = future:wait_result(100) +--- +... +ret +--- +- - [1] +... +type(ret[1]) +--- +- cdata +... +future = c.space.test:insert({5}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [5] +... +s:get{5} +--- +- [5] +... +future = c.space.test:replace({6}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [6] +... +s:get{6} +--- +- [6] +... +future = c.space.test:delete({6}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [6] +... +s:get{6} +--- +... +future = c.space.test:update({5}, {{'=', 2, 5}}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [5, 5] +... +s:get{5} +--- +- [5, 5] +... +future = c.space.test:upsert({5}, {{'=', 2, 6}}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- null +... +s:get{5} +--- +- [5, 6] +... +future = c.space.test:get({5}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [5, 6] +... +-- +-- Test index methods. +-- +future = c.space.test.index.pk:select({1}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- - [1] +... +future = c.space.test.index.pk:get({2}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [2] +... +future = c.space.test.index.pk:min({}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [1] +... +future = c.space.test.index.pk:max({}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [5, 6] +... +c:close() +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +c = net:connect(box.cfg.listen) +--- +... +future = c.space.test.index.pk:count({3}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- 1 +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +c = net:connect(box.cfg.listen) +--- +... +future = c.space.test.index.pk:delete({3}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [3] +... +s:get{3} +--- +... +future = c.space.test.index.pk:update({4}, {{'=', 2, 6}}, {is_async = true}) +--- +... +future:wait_result(100) +--- +- [4, 6] +... +s:get{4} +--- +- [4, 6] +... +-- +-- Test async errors. +-- +future = c.space.test:insert({1}, {is_async = true}) +--- +... +future:wait_result() +--- +- null +- Duplicate key exists in unique index 'pk' in space 'test' +... +future:result() +--- +- null +- Duplicate key exists in unique index 'pk' in space 'test' +... +box.schema.func.drop('long_function') +--- +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box_methods_gh-3107.test.lua b/test/box/net.box_methods_gh-3107.test.lua new file mode 100644 index 000000000..364a72ed3 --- /dev/null +++ b/test/box/net.box_methods_gh-3107.test.lua @@ -0,0 +1,96 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +ret = {} +count = 0 +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +while count ~= 10 do fiber.sleep(0.1) end +ret + +-- +-- Test space methods. +-- +c:close() +box.schema.user.grant('guest', 'read,write', 'space', 'test') +c = net:connect(box.cfg.listen) +future = c.space.test:select({1}, {is_async = true}) +ret = future:wait_result(100) +ret +type(ret[1]) +future = c.space.test:insert({5}, {is_async = true}) +future:wait_result(100) +s:get{5} +future = c.space.test:replace({6}, {is_async = true}) +future:wait_result(100) +s:get{6} +future = c.space.test:delete({6}, {is_async = true}) +future:wait_result(100) +s:get{6} +future = c.space.test:update({5}, {{'=', 2, 5}}, {is_async = true}) +future:wait_result(100) +s:get{5} +future = c.space.test:upsert({5}, {{'=', 2, 6}}, {is_async = true}) +future:wait_result(100) +s:get{5} +future = c.space.test:get({5}, {is_async = true}) +future:wait_result(100) + +-- +-- Test index methods. +-- +future = c.space.test.index.pk:select({1}, {is_async = true}) +future:wait_result(100) +future = c.space.test.index.pk:get({2}, {is_async = true}) +future:wait_result(100) +future = c.space.test.index.pk:min({}, {is_async = true}) +future:wait_result(100) +future = c.space.test.index.pk:max({}, {is_async = true}) +future:wait_result(100) +c:close() +box.schema.user.grant('guest', 'execute', 'universe') +c = net:connect(box.cfg.listen) +future = c.space.test.index.pk:count({3}, {is_async = true}) +future:wait_result(100) +c:close() +box.schema.user.revoke('guest', 'execute', 'universe') +c = net:connect(box.cfg.listen) +future = c.space.test.index.pk:delete({3}, {is_async = true}) +future:wait_result(100) +s:get{3} +future = c.space.test.index.pk:update({4}, {{'=', 2, 6}}, {is_async = true}) +future:wait_result(100) +s:get{4} + +-- +-- Test async errors. +-- +future = c.space.test:insert({1}, {is_async = true}) +future:wait_result() +future:result() + +box.schema.func.drop('long_function') + +c:close() +s:drop() diff --git a/test/box/net.box_msgpack_gh-2195.result b/test/box/net.box_msgpack_gh-2195.result new file mode 100644 index 000000000..a4c851334 --- /dev/null +++ b/test/box/net.box_msgpack_gh-2195.result @@ -0,0 +1,527 @@ +msgpack = require 'msgpack' +--- +... +test_run = require('test_run').new() +--- +... +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") +--- +- true +... +net = require('net.box') +--- +... +-- CALL vs CALL_16 in connect options +function echo(...) return ... end +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:call('echo', {42}) +--- +- 42 +... +c:eval('return echo(...)', {42}) +--- +- 42 +... +-- invalid arguments +c:call('echo', 42) +--- +- error: 'builtin/box/net_box.lua..."]:: Use remote:call(func_name, {arg1, arg2, ...}, + opts) instead of remote:call(func_name, arg1, arg2, ...)' +... +c:eval('return echo(...)', 42) +--- +- error: 'builtin/box/net_box.lua..."]:: Use remote:eval(expression, {arg1, arg2, ...}, + opts) instead of remote:eval(expression, arg1, arg2, ...)' +... +c:close() +--- +... +c = net.connect(box.cfg.listen, {call_16 = true}) +--- +... +c:call('echo', 42) +--- +- - [42] +... +c:eval('return echo(...)', 42) +--- +- 42 +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +-- +-- gh-2195 export pure msgpack from net.box +-- +space = box.schema.space.create('test') +--- +... +_ = box.space.test:create_index('primary') +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'test') +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +c = net.connect(box.cfg.listen) +--- +... +ibuf = require('buffer').ibuf() +--- +... +c:ping() +--- +- true +... +c.space.test ~= nil +--- +- true +... +c.space.test:replace({1, 'hello'}) +--- +- [1, 'hello'] +... +-- replace +c.space.test:replace({2}, {buffer = ibuf}) +--- +- 9 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [[2]]} +... +-- replace + skip_header +c.space.test:replace({2}, {buffer = ibuf, skip_header = true}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [[2]] +... +-- insert +c.space.test:insert({3}, {buffer = ibuf}) +--- +- 9 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [[3]]} +... +-- insert + skip_header +_ = space:delete({3}) +--- +... +c.space.test:insert({3}, {buffer = ibuf, skip_header = true}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [[3]] +... +-- update +c.space.test:update({3}, {}, {buffer = ibuf}) +--- +- 9 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [[3]]} +... +c.space.test.index.primary:update({3}, {}, {buffer = ibuf}) +--- +- 9 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [[3]]} +... +-- update + skip_header +c.space.test:update({3}, {}, {buffer = ibuf, skip_header = true}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [[3]] +... +c.space.test.index.primary:update({3}, {}, {buffer = ibuf, skip_header = true}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [[3]] +... +-- upsert +c.space.test:upsert({4}, {}, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +-- upsert + skip_header +c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +-- delete +c.space.test:upsert({4}, {}, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +-- delete + skip_header +c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +-- select +c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf}) +--- +- 19 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [[3], [2], [1, 'hello']]} +... +-- select + skip_header +c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf, skip_header = true}) +--- +- 17 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [[3], [2], [1, 'hello']] +... +-- select +len = c.space.test:select({}, {buffer = ibuf}) +--- +... +ibuf.rpos + len == ibuf.wpos +--- +- true +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +ibuf.rpos == ibuf.wpos +--- +- true +... +len +--- +- 21 +... +result +--- +- {48: [[1, 'hello'], [2], [3], [4]]} +... +-- select + skip_header +len = c.space.test:select({}, {buffer = ibuf, skip_header = true}) +--- +... +ibuf.rpos + len == ibuf.wpos +--- +- true +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +ibuf.rpos == ibuf.wpos +--- +- true +... +len +--- +- 19 +... +result +--- +- [[1, 'hello'], [2], [3], [4]] +... +-- call +c:call("echo", {1, 2, 3}, {buffer = ibuf}) +--- +- 10 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [1, 2, 3]} +... +c:call("echo", {}, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +c:call("echo", nil, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +-- call + skip_header +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +--- +- 8 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [1, 2, 3] +... +c:call("echo", {}, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +c:call("echo", nil, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +-- eval +c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +c:eval("echo(...)", {}, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +c:eval("echo(...)", nil, {buffer = ibuf}) +--- +- 7 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: []} +... +-- eval + skip_header +c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +c:eval("echo(...)", {}, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +c:eval("echo(...)", nil, {buffer = ibuf, skip_header = true}) +--- +- 5 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [] +... +-- make several request into a buffer with skip_header, then read +-- results +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +--- +- 8 +... +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +--- +- 8 +... +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +--- +- 8 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [1, 2, 3] +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [1, 2, 3] +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- [1, 2, 3] +... +-- unsupported methods +c.space.test:get({1}, { buffer = ibuf}) +--- +- error: 'builtin/box/net_box.lua..."]:: index:get() doesn''t support `buffer` argument' +... +c.space.test.index.primary:min({}, { buffer = ibuf}) +--- +- error: 'builtin/box/net_box.lua..."]:: index:min() doesn''t support `buffer` argument' +... +c.space.test.index.primary:max({}, { buffer = ibuf}) +--- +- error: 'builtin/box/net_box.lua..."]:: index:max() doesn''t support `buffer` argument' +... +c.space.test.index.primary:count({}, { buffer = ibuf}) +--- +- error: 'builtin/box/net_box.lua..."]:: index:count() doesn''t support `buffer` argument' +... +c.space.test.index.primary:get({1}, { buffer = ibuf}) +--- +- error: 'builtin/box/net_box.lua..."]:: index:get() doesn''t support `buffer` argument' +... +-- error handling +rpos, wpos = ibuf.rpos, ibuf.wpos +--- +... +c.space.test:insert({1}, {buffer = ibuf}) +--- +- error: Duplicate key exists in unique index 'primary' in space 'test' +... +ibuf.rpos == rpos, ibuf.wpos == wpos +--- +- true +- true +... +ibuf = nil +--- +... +c:close() +--- +... +space:drop() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_msgpack_gh-2195.test.lua b/test/box/net.box_msgpack_gh-2195.test.lua new file mode 100644 index 000000000..8c14b4b43 --- /dev/null +++ b/test/box/net.box_msgpack_gh-2195.test.lua @@ -0,0 +1,192 @@ +msgpack = require 'msgpack' +test_run = require('test_run').new() +test_run:cmd("push filter ".."'\\.lua.*:[0-9]+: ' to '.lua...\"]:: '") +net = require('net.box') + +-- CALL vs CALL_16 in connect options +function echo(...) return ... end +box.schema.user.grant('guest', 'execute', 'universe') +c = net.connect(box.cfg.listen) +c:call('echo', {42}) +c:eval('return echo(...)', {42}) +-- invalid arguments +c:call('echo', 42) +c:eval('return echo(...)', 42) +c:close() +c = net.connect(box.cfg.listen, {call_16 = true}) +c:call('echo', 42) +c:eval('return echo(...)', 42) +c:close() +box.schema.user.revoke('guest', 'execute', 'universe') + +-- +-- gh-2195 export pure msgpack from net.box +-- + +space = box.schema.space.create('test') +_ = box.space.test:create_index('primary') +box.schema.user.grant('guest', 'read,write', 'space', 'test') +box.schema.user.grant('guest', 'execute', 'universe') +c = net.connect(box.cfg.listen) +ibuf = require('buffer').ibuf() + +c:ping() +c.space.test ~= nil + +c.space.test:replace({1, 'hello'}) + +-- replace +c.space.test:replace({2}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- replace + skip_header +c.space.test:replace({2}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- insert +c.space.test:insert({3}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- insert + skip_header +_ = space:delete({3}) +c.space.test:insert({3}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- update +c.space.test:update({3}, {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c.space.test.index.primary:update({3}, {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- update + skip_header +c.space.test:update({3}, {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c.space.test.index.primary:update({3}, {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- upsert +c.space.test:upsert({4}, {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- upsert + skip_header +c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- delete +c.space.test:upsert({4}, {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- delete + skip_header +c.space.test:upsert({4}, {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- select +c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- select + skip_header +c.space.test.index.primary:select({3}, {iterator = 'LE', buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- select +len = c.space.test:select({}, {buffer = ibuf}) +ibuf.rpos + len == ibuf.wpos +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +ibuf.rpos == ibuf.wpos +len +result + +-- select + skip_header +len = c.space.test:select({}, {buffer = ibuf, skip_header = true}) +ibuf.rpos + len == ibuf.wpos +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +ibuf.rpos == ibuf.wpos +len +result + +-- call +c:call("echo", {1, 2, 3}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:call("echo", {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:call("echo", nil, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- call + skip_header +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:call("echo", {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:call("echo", nil, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- eval +c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:eval("echo(...)", {}, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:eval("echo(...)", nil, {buffer = ibuf}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- eval + skip_header +c:eval("echo(...)", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:eval("echo(...)", {}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +c:eval("echo(...)", nil, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- make several request into a buffer with skip_header, then read +-- results +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +c:call("echo", {1, 2, 3}, {buffer = ibuf, skip_header = true}) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +-- unsupported methods +c.space.test:get({1}, { buffer = ibuf}) +c.space.test.index.primary:min({}, { buffer = ibuf}) +c.space.test.index.primary:max({}, { buffer = ibuf}) +c.space.test.index.primary:count({}, { buffer = ibuf}) +c.space.test.index.primary:get({1}, { buffer = ibuf}) + +-- error handling +rpos, wpos = ibuf.rpos, ibuf.wpos +c.space.test:insert({1}, {buffer = ibuf}) +ibuf.rpos == rpos, ibuf.wpos == wpos + +ibuf = nil +c:close() +space:drop() +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_on_schema_reload-gh-1904.result b/test/box/net.box_on_schema_reload-gh-1904.result new file mode 100644 index 000000000..5029684bf --- /dev/null +++ b/test/box/net.box_on_schema_reload-gh-1904.result @@ -0,0 +1,102 @@ +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +space = box.schema.space.create('net_box_test_space') +--- +... +index = space:create_index('primary', { type = 'tree' }) +--- +... +box.schema.user.create('netbox', { password = 'test' }) +--- +... +box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') +--- +... +box.schema.user.grant('netbox', 'execute', 'universe') +--- +... +net = require('net.box') +--- +... +-- gh-1904 net.box hangs in :close() if a fiber was cancelled +-- while blocked in :_wait_state() in :_request() +options = {user = 'netbox', password = 'badpass', wait_connected = false, reconnect_after = 0.01} +--- +... +c = net:new(box.cfg.listen, options) +--- +... +f = fiber.create(function() c:call("") end) +--- +... +fiber.sleep(0.01) +--- +... +f:cancel(); c:close() +--- +... +box.schema.user.grant('guest', 'read', 'space', '_schema') +--- +... +-- check for on_schema_reload callback +test_run:cmd("setopt delimiter ';'") +--- +- true +... +do + local a = 0 + function osr_cb() + a = a + 1 + end + local con = net.new(box.cfg.listen, { + wait_connected = false + }) + con:on_schema_reload(osr_cb) + con:wait_connected() + con.space._schema:select{} + box.schema.space.create('misisipi') + box.space.misisipi:drop() + con.space._schema:select{} + con:close() + con = nil + + return a +end; +--- +- 2 +... +do + local a = 0 + function osr_cb() + a = a + 1 + end + local con = net.new(box.cfg.listen, { + wait_connected = true + }) + con:on_schema_reload(osr_cb) + con.space._schema:select{} + box.schema.space.create('misisipi') + box.space.misisipi:drop() + con.space._schema:select{} + con:close() + con = nil + + return a +end; +--- +- 1 +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +box.schema.user.revoke('guest', 'read', 'space', '_schema') +--- +... diff --git a/test/box/net.box_on_schema_reload-gh-1904.test.lua b/test/box/net.box_on_schema_reload-gh-1904.test.lua new file mode 100644 index 000000000..eeb9def65 --- /dev/null +++ b/test/box/net.box_on_schema_reload-gh-1904.test.lua @@ -0,0 +1,65 @@ +fiber = require 'fiber' +test_run = require('test_run').new() + +LISTEN = require('uri').parse(box.cfg.listen) +space = box.schema.space.create('net_box_test_space') +index = space:create_index('primary', { type = 'tree' }) + +box.schema.user.create('netbox', { password = 'test' }) +box.schema.user.grant('netbox', 'read,write', 'space', 'net_box_test_space') +box.schema.user.grant('netbox', 'execute', 'universe') + +net = require('net.box') + +-- gh-1904 net.box hangs in :close() if a fiber was cancelled +-- while blocked in :_wait_state() in :_request() +options = {user = 'netbox', password = 'badpass', wait_connected = false, reconnect_after = 0.01} +c = net:new(box.cfg.listen, options) +f = fiber.create(function() c:call("") end) +fiber.sleep(0.01) +f:cancel(); c:close() + +box.schema.user.grant('guest', 'read', 'space', '_schema') + +-- check for on_schema_reload callback +test_run:cmd("setopt delimiter ';'") +do + local a = 0 + function osr_cb() + a = a + 1 + end + local con = net.new(box.cfg.listen, { + wait_connected = false + }) + con:on_schema_reload(osr_cb) + con:wait_connected() + con.space._schema:select{} + box.schema.space.create('misisipi') + box.space.misisipi:drop() + con.space._schema:select{} + con:close() + con = nil + + return a +end; +do + local a = 0 + function osr_cb() + a = a + 1 + end + local con = net.new(box.cfg.listen, { + wait_connected = true + }) + con:on_schema_reload(osr_cb) + con.space._schema:select{} + box.schema.space.create('misisipi') + box.space.misisipi:drop() + con.space._schema:select{} + con:close() + con = nil + + return a +end; +test_run:cmd("setopt delimiter ''"); + +box.schema.user.revoke('guest', 'read', 'space', '_schema') diff --git a/test/box/net.box_password_gh-1545.result b/test/box/net.box_password_gh-1545.result new file mode 100644 index 000000000..984084cae --- /dev/null +++ b/test/box/net.box_password_gh-1545.result @@ -0,0 +1,28 @@ +remote = require 'net.box' +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +-- #1545 empty password +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'test' }) +--- +... +cn ~= nil +--- +- true +... +cn:close() +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service, { password = 'test' }) +--- +- error: 'net.box: user is not defined' +... +cn ~= nil +--- +- true +... +cn:close() +--- +... diff --git a/test/box/net.box_password_gh-1545.test.lua b/test/box/net.box_password_gh-1545.test.lua new file mode 100644 index 000000000..86d496432 --- /dev/null +++ b/test/box/net.box_password_gh-1545.test.lua @@ -0,0 +1,10 @@ +remote = require 'net.box' +LISTEN = require('uri').parse(box.cfg.listen) + +-- #1545 empty password +cn = remote.connect(LISTEN.host, LISTEN.service, { user = 'test' }) +cn ~= nil +cn:close() +cn = remote.connect(LISTEN.host, LISTEN.service, { password = 'test' }) +cn ~= nil +cn:close() diff --git a/test/box/net.box_permissions.result b/test/box/net.box_permissions.result new file mode 100644 index 000000000..04729dccb --- /dev/null +++ b/test/box/net.box_permissions.result @@ -0,0 +1,186 @@ +remote = require 'net.box' +--- +... +fiber = require 'fiber' +--- +... +log = require 'log' +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +space = box.schema.space.create('net_box_test_space') +--- +... +index = space:create_index('primary', { type = 'tree' }) +--- +... +-- low level connection +log.info("create connection") +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service) +--- +... +log.info("state is %s", cn.state) +--- +... +cn:ping() +--- +- true +... +log.info("ping is done") +--- +... +cn:ping() +--- +- true +... +log.info("ping is done") +--- +... +cn:ping() +--- +- true +... +-- check permissions +cn:call('unexists_procedure') +--- +- error: Execute access to function 'unexists_procedure' is denied for user 'guest' +... +function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end +--- +... +cn:call('test_foo', {'a', 'b', 'c'}) +--- +- error: Execute access to function 'test_foo' is denied for user 'guest' +... +cn:eval('return 2+2') +--- +- error: Execute access to universe '' is denied for user 'guest' +... +cn:close() +--- +... +-- connect and call without usage access +box.schema.user.grant('guest','execute','universe') +--- +... +box.schema.user.revoke('guest','usage','universe') +--- +... +box.session.su("guest") +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service) +--- +... +cn:call('test_foo', {'a', 'b', 'c'}) +--- +- error: Usage access to universe '' is denied for user 'guest' +... +box.session.su("admin") +--- +... +box.schema.user.grant('guest','usage','universe') +--- +... +cn:close() +--- +... +cn = remote.connect(box.cfg.listen) +--- +... +cn:call('unexists_procedure') +--- +- error: Procedure 'unexists_procedure' is not defined +... +cn:call('test_foo', {'a', 'b', 'c'}) +--- +- [[{'a': 1}], [{'b': 2}], 'c'] +... +cn:call(nil, {'a', 'b', 'c'}) +--- +- error: Procedure 'nil' is not defined +... +cn:eval('return 2+2') +--- +- 4 +... +cn:eval('return 1, 2, 3') +--- +- 1 +- 2 +- 3 +... +cn:eval('return ...', {1, 2, 3}) +--- +- 1 +- 2 +- 3 +... +cn:eval('return { k = "v1" }, true, { xx = 10, yy = 15 }, nil') +--- +- {'k': 'v1'} +- true +- {'yy': 15, 'xx': 10} +- null +... +cn:eval('return nil') +--- +- null +... +cn:eval('return') +--- +... +cn:eval('error("exception")') +--- +- error: 'eval:1: exception' +... +cn:eval('box.error(0)') +--- +- error: Unknown error +... +cn:eval('!invalid expression') +--- +- error: 'eval:1: unexpected symbol near ''!''' +... +-- box.commit() missing at return of CALL/EVAL +function no_commit() box.begin() fiber.sleep(0.001) end +--- +... +cn:call('no_commit') +--- +- error: Transaction is active at return from function +... +cn:eval('no_commit()') +--- +- error: Transaction is active at return from function +... +remote.self:eval('return 1+1, 2+2') +--- +- 2 +- 4 +... +remote.self:eval('return') +--- +... +remote.self:eval('error("exception")') +--- +- error: '[string "error("exception")"]:1: exception' +... +remote.self:eval('box.error(0)') +--- +- error: Unknown error +... +remote.self:eval('!invalid expression') +--- +- error: '[string "return !invalid expression"]:1: unexpected symbol near ''!''' +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +cn:close() +--- +... diff --git a/test/box/net.box_permissions.test.lua b/test/box/net.box_permissions.test.lua new file mode 100644 index 000000000..249604f64 --- /dev/null +++ b/test/box/net.box_permissions.test.lua @@ -0,0 +1,66 @@ +remote = require 'net.box' +fiber = require 'fiber' +log = require 'log' + +LISTEN = require('uri').parse(box.cfg.listen) +space = box.schema.space.create('net_box_test_space') +index = space:create_index('primary', { type = 'tree' }) + +-- low level connection +log.info("create connection") +cn = remote.connect(LISTEN.host, LISTEN.service) +log.info("state is %s", cn.state) + +cn:ping() +log.info("ping is done") +cn:ping() +log.info("ping is done") + + +cn:ping() + + +-- check permissions +cn:call('unexists_procedure') +function test_foo(a,b,c) return { {{ [a] = 1 }}, {{ [b] = 2 }}, c } end +cn:call('test_foo', {'a', 'b', 'c'}) +cn:eval('return 2+2') +cn:close() +-- connect and call without usage access +box.schema.user.grant('guest','execute','universe') +box.schema.user.revoke('guest','usage','universe') +box.session.su("guest") +cn = remote.connect(LISTEN.host, LISTEN.service) +cn:call('test_foo', {'a', 'b', 'c'}) +box.session.su("admin") +box.schema.user.grant('guest','usage','universe') +cn:close() +cn = remote.connect(box.cfg.listen) + +cn:call('unexists_procedure') +cn:call('test_foo', {'a', 'b', 'c'}) +cn:call(nil, {'a', 'b', 'c'}) +cn:eval('return 2+2') +cn:eval('return 1, 2, 3') +cn:eval('return ...', {1, 2, 3}) +cn:eval('return { k = "v1" }, true, { xx = 10, yy = 15 }, nil') +cn:eval('return nil') +cn:eval('return') +cn:eval('error("exception")') +cn:eval('box.error(0)') +cn:eval('!invalid expression') + +-- box.commit() missing at return of CALL/EVAL +function no_commit() box.begin() fiber.sleep(0.001) end +cn:call('no_commit') +cn:eval('no_commit()') + +remote.self:eval('return 1+1, 2+2') +remote.self:eval('return') +remote.self:eval('error("exception")') +remote.self:eval('box.error(0)') +remote.self:eval('!invalid expression') + +box.schema.user.revoke('guest', 'execute', 'universe') + +cn:close() diff --git a/test/box/net.box_pseudo_objects_gh-2401.result b/test/box/net.box_pseudo_objects_gh-2401.result new file mode 100644 index 000000000..46730368f --- /dev/null +++ b/test/box/net.box_pseudo_objects_gh-2401.result @@ -0,0 +1,55 @@ +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +-- +-- gh-2401 update pseudo objects not replace them +-- +space = box.schema.space.create('test') +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +c = net.connect(box.cfg.listen) +--- +... +cspace = c.space.test +--- +... +space.index.test_index == nil +--- +- true +... +cspace.index.test_index == nil +--- +- true +... +_ = space:create_index("test_index", {parts={1, 'string'}}) +--- +... +c:reload_schema() +--- +... +space.index.test_index ~= nil +--- +- true +... +cspace.index.test_index ~= nil +--- +- true +... +c.space.test.index.test_index ~= nil +--- +- true +... +-- cleanup +space:drop() +--- +... diff --git a/test/box/net.box_pseudo_objects_gh-2401.test.lua b/test/box/net.box_pseudo_objects_gh-2401.test.lua new file mode 100644 index 000000000..b9277ae94 --- /dev/null +++ b/test/box/net.box_pseudo_objects_gh-2401.test.lua @@ -0,0 +1,23 @@ +test_run = require('test_run').new() +net = require('net.box') + +test_run:cmd('create server connecter with script = "box/proxy.lua"') + +-- +-- gh-2401 update pseudo objects not replace them +-- +space = box.schema.space.create('test') +box.schema.user.grant('guest', 'read', 'space', 'test') +c = net.connect(box.cfg.listen) +cspace = c.space.test +space.index.test_index == nil +cspace.index.test_index == nil +_ = space:create_index("test_index", {parts={1, 'string'}}) +c:reload_schema() +space.index.test_index ~= nil +cspace.index.test_index ~= nil +c.space.test.index.test_index ~= nil + +-- cleanup + +space:drop() diff --git a/test/box/net.box_raw_response_gh-3107.result b/test/box/net.box_raw_response_gh-3107.result new file mode 100644 index 000000000..85fef9daf --- /dev/null +++ b/test/box/net.box_raw_response_gh-3107.result @@ -0,0 +1,123 @@ +fiber = require 'fiber' +--- +... +msgpack = require 'msgpack' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +ret = {} +--- +... +count = 0 +--- +... +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +--- +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +while count ~= 10 do fiber.sleep(0.1) end +--- +... +ret +--- +- - &0 [1, 2, 3] + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 +... +-- +-- Test raw response getting. +-- +ibuf = require('buffer').ibuf() +--- +... +future = c:call('long_function', {1, 2, 3}, {is_async = true, buffer = ibuf}) +--- +... +finalize_long() +--- +... +future:wait_result(100) +--- +- 10 +... +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +--- +... +result +--- +- {48: [1, 2, 3]} +... +box.schema.func.drop('long_function') +--- +... +c:close() +--- +... +s:drop() +--- +... diff --git a/test/box/net.box_raw_response_gh-3107.test.lua b/test/box/net.box_raw_response_gh-3107.test.lua new file mode 100644 index 000000000..fa477d6d7 --- /dev/null +++ b/test/box/net.box_raw_response_gh-3107.test.lua @@ -0,0 +1,46 @@ +fiber = require 'fiber' +msgpack = require 'msgpack' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +ret = {} +count = 0 +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +while count ~= 10 do fiber.sleep(0.1) end +ret + +-- +-- Test raw response getting. +-- +ibuf = require('buffer').ibuf() +future = c:call('long_function', {1, 2, 3}, {is_async = true, buffer = ibuf}) +finalize_long() +future:wait_result(100) +result, ibuf.rpos = msgpack.decode_unchecked(ibuf.rpos) +result + +box.schema.func.drop('long_function') + +c:close() +s:drop() diff --git a/test/box/net.box_readahead_gh-3958.result b/test/box/net.box_readahead_gh-3958.result new file mode 100644 index 000000000..fc2093531 --- /dev/null +++ b/test/box/net.box_readahead_gh-3958.result @@ -0,0 +1,55 @@ +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +-- +-- gh-3958 updating box.cfg.readahead doesn't affect existing connections. +-- +readahead = box.cfg.readahead +--- +... +box.cfg{readahead = 128} +--- +... +s = box.schema.space.create("test") +--- +... +_ = s:create_index("pk") +--- +... +box.schema.user.grant("guest", "read,write", "space", "test") +--- +... +-- connection is created with small readahead value, +-- make sure it is updated if box.cfg.readahead is changed. +c = net.connect(box.cfg.listen) +--- +... +box.cfg{readahead = 100 * 1024} +--- +... +box.error.injection.set("ERRINJ_WAL_DELAY", true) +--- +- ok +... +pad = string.rep('x', 8192) +--- +... +for i = 1, 5 do c.space.test:replace({i, pad}, {is_async = true}) end +--- +... +box.error.injection.set("ERRINJ_WAL_DELAY", false) +--- +- ok +... +test_run:wait_log('default', 'readahead limit is reached', 1024, 0.1) +--- +... +s:drop() +--- +... +box.cfg{readahead = readahead} +--- +... diff --git a/test/box/net.box_readahead_gh-3958.test.lua b/test/box/net.box_readahead_gh-3958.test.lua new file mode 100644 index 000000000..1e33a84cb --- /dev/null +++ b/test/box/net.box_readahead_gh-3958.test.lua @@ -0,0 +1,29 @@ +test_run = require('test_run').new() +net = require('net.box') + +-- +-- gh-3958 updating box.cfg.readahead doesn't affect existing connections. +-- +readahead = box.cfg.readahead + +box.cfg{readahead = 128} + +s = box.schema.space.create("test") +_ = s:create_index("pk") +box.schema.user.grant("guest", "read,write", "space", "test") + +-- connection is created with small readahead value, +-- make sure it is updated if box.cfg.readahead is changed. +c = net.connect(box.cfg.listen) + +box.cfg{readahead = 100 * 1024} + +box.error.injection.set("ERRINJ_WAL_DELAY", true) +pad = string.rep('x', 8192) +for i = 1, 5 do c.space.test:replace({i, pad}, {is_async = true}) end +box.error.injection.set("ERRINJ_WAL_DELAY", false) + +test_run:wait_log('default', 'readahead limit is reached', 1024, 0.1) + +s:drop() +box.cfg{readahead = readahead} diff --git a/test/box/net.box_reconnect_after.result b/test/box/net.box_reconnect_after.result new file mode 100644 index 000000000..a75f9dc5c --- /dev/null +++ b/test/box/net.box_reconnect_after.result @@ -0,0 +1,32 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +-- +-- Test a case, when netbox can not connect first time, but +-- reconnect_after is set. +-- +c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false}) +--- +... +while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end +--- +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +c.state +--- +- closed +... +c = nil +--- +... diff --git a/test/box/net.box_reconnect_after.test.lua b/test/box/net.box_reconnect_after.test.lua new file mode 100644 index 000000000..8ad870475 --- /dev/null +++ b/test/box/net.box_reconnect_after.test.lua @@ -0,0 +1,16 @@ +fiber = require 'fiber' +net = require('net.box') + +box.schema.user.grant('guest', 'execute', 'universe') + +-- +-- Test a case, when netbox can not connect first time, but +-- reconnect_after is set. +-- +c = net.connect('localhost:33333', {reconnect_after = 0.1, wait_connected = false}) +while c.state ~= 'error_reconnect' do fiber.sleep(0.01) end +c:close() + +box.schema.user.revoke('guest', 'execute', 'universe') +c.state +c = nil diff --git a/test/box/net.box_reconnect_after_gh-3164.result b/test/box/net.box_reconnect_after_gh-3164.result new file mode 100644 index 000000000..216ce0366 --- /dev/null +++ b/test/box/net.box_reconnect_after_gh-3164.result @@ -0,0 +1,119 @@ +fiber = require 'fiber' +--- +... +log = require 'log' +--- +... +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +test_run:cmd('create server connecter with script = "box/proxy.lua"') +--- +- true +... +-- +-- gh-3164: netbox connection is not closed and garbage collected +-- ever, if reconnect_after is set. +-- +test_run:cmd('start server connecter') +--- +- true +... +test_run:cmd("set variable connect_to to 'connecter.listen'") +--- +- true +... +weak = setmetatable({}, {__mode = 'v'}) +--- +... +-- Create strong and weak reference. Weak is valid until strong +-- is valid too. +strong = net.connect(connect_to, {reconnect_after = 0.1}) +--- +... +weak.c = strong +--- +... +weak.c:ping() +--- +- true +... +test_run:cmd('stop server connecter') +--- +- true +... +test_run:cmd('cleanup server connecter') +--- +- true +... +-- Check the connection tries to reconnect at least two times. +-- 'Cannot assign requested address' is the crutch for running the +-- tests in a docker. This error emits instead of +-- 'Connection refused' inside a docker. +old_log_level = box.cfg.log_level +--- +... +box.cfg{log_level = 6} +--- +... +log.info(string.rep('a', 1000)) +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and + test_run:grep_log('default', 'Connection refused', 1000) == nil and + test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do + fiber.sleep(0.1) +end; +--- +... +log.info(string.rep('a', 1000)); +--- +... +while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and + test_run:grep_log('default', 'Connection refused', 1000) == nil and + test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do + fiber.sleep(0.1) +end; +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +box.cfg{log_level = old_log_level} +--- +... +collectgarbage('collect') +--- +- 0 +... +strong.state +--- +- error_reconnect +... +strong == weak.c +--- +- true +... +-- Remove single strong reference. Now connection must be garbage +-- collected. +strong = nil +--- +... +collectgarbage('collect') +--- +- 0 +... +-- Now weak.c is null, because it was weak reference, and the +-- connection is deleted by 'collect'. +weak.c +--- +- null +... diff --git a/test/box/net.box_reconnect_after_gh-3164.test.lua b/test/box/net.box_reconnect_after_gh-3164.test.lua new file mode 100644 index 000000000..dc2747080 --- /dev/null +++ b/test/box/net.box_reconnect_after_gh-3164.test.lua @@ -0,0 +1,52 @@ +fiber = require 'fiber' +log = require 'log' +test_run = require('test_run').new() +net = require('net.box') + +test_run:cmd('create server connecter with script = "box/proxy.lua"') + +-- +-- gh-3164: netbox connection is not closed and garbage collected +-- ever, if reconnect_after is set. +-- +test_run:cmd('start server connecter') +test_run:cmd("set variable connect_to to 'connecter.listen'") +weak = setmetatable({}, {__mode = 'v'}) +-- Create strong and weak reference. Weak is valid until strong +-- is valid too. +strong = net.connect(connect_to, {reconnect_after = 0.1}) +weak.c = strong +weak.c:ping() +test_run:cmd('stop server connecter') +test_run:cmd('cleanup server connecter') +-- Check the connection tries to reconnect at least two times. +-- 'Cannot assign requested address' is the crutch for running the +-- tests in a docker. This error emits instead of +-- 'Connection refused' inside a docker. +old_log_level = box.cfg.log_level +box.cfg{log_level = 6} +log.info(string.rep('a', 1000)) +test_run:cmd("setopt delimiter ';'") +while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and + test_run:grep_log('default', 'Connection refused', 1000) == nil and + test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do + fiber.sleep(0.1) +end; +log.info(string.rep('a', 1000)); +while test_run:grep_log('default', 'Network is unreachable', 1000) == nil and + test_run:grep_log('default', 'Connection refused', 1000) == nil and + test_run:grep_log('default', 'Cannot assign requested address', 1000) == nil do + fiber.sleep(0.1) +end; +test_run:cmd("setopt delimiter ''"); +box.cfg{log_level = old_log_level} +collectgarbage('collect') +strong.state +strong == weak.c +-- Remove single strong reference. Now connection must be garbage +-- collected. +strong = nil +collectgarbage('collect') +-- Now weak.c is null, because it was weak reference, and the +-- connection is deleted by 'collect'. +weak.c diff --git a/test/box/net.box_reload_schema_gh-636.result b/test/box/net.box_reload_schema_gh-636.result new file mode 100644 index 000000000..43e8e8b29 --- /dev/null +++ b/test/box/net.box_reload_schema_gh-636.result @@ -0,0 +1,108 @@ +remote = require 'net.box' +--- +... +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +-- #636: Reload schema on demand +sp = box.schema.space.create('test_old') +--- +... +_ = sp:create_index('primary') +--- +... +sp:insert{1, 2, 3} +--- +- [1, 2, 3] +... +box.schema.user.grant('guest', 'read', 'space', 'test_old') +--- +... +con = remote.new(box.cfg.listen) +--- +... +con:ping() +--- +- true +... +con.space.test_old:select{} +--- +- - [1, 2, 3] +... +con.space.test == nil +--- +- true +... +sp = box.schema.space.create('test') +--- +... +_ = sp:create_index('primary') +--- +... +sp:insert{2, 3, 4} +--- +- [2, 3, 4] +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +con.space.test == nil +--- +- true +... +con:reload_schema() +--- +... +con.space.test:select{} +--- +- - [2, 3, 4] +... +box.space.test:drop() +--- +... +box.space.test_old:drop() +--- +... +con:close() +--- +... +name = string.match(arg[0], "([^,]+)%.lua") +--- +... +file_log = require('fio').open(name .. '.log', {'O_RDONLY', 'O_NONBLOCK'}) +--- +... +file_log:seek(0, 'SEEK_END') ~= 0 +--- +- true +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +_ = fiber.create( + function() + local conn = require('net.box').new(box.cfg.listen) + conn:call('no_such_function', {}) + conn:close() + end +); +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +test_run:wait_log('default', 'ER_NO_SUCH_PROC', nil, 10) +--- +- ER_NO_SUCH_PROC +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_reload_schema_gh-636.test.lua b/test/box/net.box_reload_schema_gh-636.test.lua new file mode 100644 index 000000000..d7431ee6c --- /dev/null +++ b/test/box/net.box_reload_schema_gh-636.test.lua @@ -0,0 +1,46 @@ +remote = require 'net.box' +fiber = require 'fiber' +test_run = require('test_run').new() + +-- #636: Reload schema on demand +sp = box.schema.space.create('test_old') +_ = sp:create_index('primary') +sp:insert{1, 2, 3} + +box.schema.user.grant('guest', 'read', 'space', 'test_old') +con = remote.new(box.cfg.listen) +con:ping() +con.space.test_old:select{} +con.space.test == nil + +sp = box.schema.space.create('test') +_ = sp:create_index('primary') +sp:insert{2, 3, 4} + +box.schema.user.grant('guest', 'read', 'space', 'test') + +con.space.test == nil +con:reload_schema() +con.space.test:select{} + +box.space.test:drop() +box.space.test_old:drop() +con:close() + +name = string.match(arg[0], "([^,]+)%.lua") +file_log = require('fio').open(name .. '.log', {'O_RDONLY', 'O_NONBLOCK'}) +file_log:seek(0, 'SEEK_END') ~= 0 + +box.schema.user.grant('guest', 'execute', 'universe') +test_run:cmd("setopt delimiter ';'") + +_ = fiber.create( + function() + local conn = require('net.box').new(box.cfg.listen) + conn:call('no_such_function', {}) + conn:close() + end +); +test_run:cmd("setopt delimiter ''"); +test_run:wait_log('default', 'ER_NO_SUCH_PROC', nil, 10) +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_remote_method_gh-544.result b/test/box/net.box_remote_method_gh-544.result new file mode 100644 index 000000000..bb92ba998 --- /dev/null +++ b/test/box/net.box_remote_method_gh-544.result @@ -0,0 +1,95 @@ +remote = require 'net.box' +--- +... +LISTEN = require('uri').parse(box.cfg.listen) +--- +... +box.schema.user.create('netbox', { password = 'test' }) +--- +... +-- #544 usage for remote[point]method +cn = remote.connect(LISTEN.host, LISTEN.service) +--- +... +box.schema.user.grant('guest', 'execute', 'universe') +--- +... +cn:close() +--- +... +cn = remote.connect(LISTEN.host, LISTEN.service) +--- +... +cn:eval('return true') +--- +- true +... +cn.eval('return true') +--- +- error: 'Use remote:eval(...) instead of remote.eval(...):' +... +cn.ping() +--- +- error: 'Use remote:ping(...) instead of remote.ping(...):' +... +cn:close() +--- +... +remote.self:eval('return true') +--- +- true +... +remote.self.eval('return true') +--- +- error: 'Use remote:eval(...) instead of remote.eval(...):' +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... +-- uri as the first argument +uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service) +--- +... +cn = remote.new(uri) +--- +... +cn:ping() +--- +- true +... +cn:close() +--- +... +uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) +--- +... +cn = remote.new(uri) +--- +... +cn ~= nil, cn.state, cn.error +--- +- true +- error +- Incorrect password supplied for user 'netbox' +... +cn:close() +--- +... +-- don't merge creds from uri & opts +remote.new(uri, { password = 'test' }) +--- +- error: 'net.box: user is not defined' +... +cn = remote.new(uri, { user = 'netbox', password = 'test' }) +--- +... +cn:ping() +--- +- true +... +cn:close() +--- +... +box.schema.user.drop('netbox') +--- +... diff --git a/test/box/net.box_remote_method_gh-544.test.lua b/test/box/net.box_remote_method_gh-544.test.lua new file mode 100644 index 000000000..cfd883be0 --- /dev/null +++ b/test/box/net.box_remote_method_gh-544.test.lua @@ -0,0 +1,40 @@ +remote = require 'net.box' + +LISTEN = require('uri').parse(box.cfg.listen) +box.schema.user.create('netbox', { password = 'test' }) + +-- #544 usage for remote[point]method +cn = remote.connect(LISTEN.host, LISTEN.service) + +box.schema.user.grant('guest', 'execute', 'universe') +cn:close() +cn = remote.connect(LISTEN.host, LISTEN.service) +cn:eval('return true') +cn.eval('return true') + +cn.ping() + +cn:close() + +remote.self:eval('return true') +remote.self.eval('return true') +box.schema.user.revoke('guest', 'execute', 'universe') + +-- uri as the first argument +uri = string.format('%s:%s@%s:%s', 'netbox', 'test', LISTEN.host, LISTEN.service) + +cn = remote.new(uri) +cn:ping() +cn:close() + +uri = string.format('%s@%s:%s', 'netbox', LISTEN.host, LISTEN.service) +cn = remote.new(uri) +cn ~= nil, cn.state, cn.error +cn:close() +-- don't merge creds from uri & opts +remote.new(uri, { password = 'test' }) +cn = remote.new(uri, { user = 'netbox', password = 'test' }) +cn:ping() +cn:close() + +box.schema.user.drop('netbox') diff --git a/test/box/net.box_roll_back_gh-822.result b/test/box/net.box_roll_back_gh-822.result new file mode 100644 index 000000000..5a0550e39 --- /dev/null +++ b/test/box/net.box_roll_back_gh-822.result @@ -0,0 +1,68 @@ +remote = require 'net.box' +--- +... +test_run = require('test_run').new() +--- +... +-- +-- gh-822: net.box.call should roll back local transaction on error +-- +_ = box.schema.space.create('gh822') +--- +... +_ = box.space.gh822:create_index('primary') +--- +... +test_run:cmd("setopt delimiter ';'") +--- +- true +... +-- rollback on invalid function +function rollback_on_invalid_function() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.call, remote.self, 'invalid_function') + return box.space.gh822:get(1) == nil +end; +--- +... +rollback_on_invalid_function(); +--- +- true +... +-- rollback on call error +function test_error() error('Some error') end; +--- +... +function rollback_on_call_error() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.call, remote.self, 'test_error') + return box.space.gh822:get(1) == nil +end; +--- +... +rollback_on_call_error(); +--- +- true +... +-- rollback on eval +function rollback_on_eval_error() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.eval, remote.self, "error('Some error')") + return box.space.gh822:get(1) == nil +end; +--- +... +rollback_on_eval_error(); +--- +- true +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +box.space.gh822:drop() +--- +... diff --git a/test/box/net.box_roll_back_gh-822.test.lua b/test/box/net.box_roll_back_gh-822.test.lua new file mode 100644 index 000000000..8f4754902 --- /dev/null +++ b/test/box/net.box_roll_back_gh-822.test.lua @@ -0,0 +1,42 @@ +remote = require 'net.box' +test_run = require('test_run').new() + +-- +-- gh-822: net.box.call should roll back local transaction on error +-- + +_ = box.schema.space.create('gh822') +_ = box.space.gh822:create_index('primary') + +test_run:cmd("setopt delimiter ';'") + +-- rollback on invalid function +function rollback_on_invalid_function() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.call, remote.self, 'invalid_function') + return box.space.gh822:get(1) == nil +end; +rollback_on_invalid_function(); + +-- rollback on call error +function test_error() error('Some error') end; +function rollback_on_call_error() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.call, remote.self, 'test_error') + return box.space.gh822:get(1) == nil +end; +rollback_on_call_error(); + +-- rollback on eval +function rollback_on_eval_error() + box.begin() + box.space.gh822:insert{1, "netbox_test"} + pcall(remote.self.eval, remote.self, "error('Some error')") + return box.space.gh822:get(1) == nil +end; +rollback_on_eval_error(); + +test_run:cmd("setopt delimiter ''"); +box.space.gh822:drop() diff --git a/test/box/net.box_schema_change_gh-2666.result b/test/box/net.box_schema_change_gh-2666.result new file mode 100644 index 000000000..bce46bd59 --- /dev/null +++ b/test/box/net.box_schema_change_gh-2666.result @@ -0,0 +1,79 @@ +net = require('net.box') +--- +... +-- +-- gh-2666: check that netbox.call is not repeated on schema +-- change. +-- +box.schema.user.grant('guest', 'write', 'space', '_space') +--- +... +box.schema.user.grant('guest', 'write', 'space', '_schema') +--- +... +box.schema.user.grant('guest', 'create', 'universe') +--- +... +count = 0 +--- +... +function create_space(name) count = count + 1 box.schema.create_space(name) return true end +--- +... +box.schema.func.create('create_space') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'create_space') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:call('create_space', {'test1'}) +--- +- true +... +count +--- +- 1 +... +c:call('create_space', {'test2'}) +--- +- true +... +count +--- +- 2 +... +c:call('create_space', {'test3'}) +--- +- true +... +count +--- +- 3 +... +box.space.test1:drop() +--- +... +box.space.test2:drop() +--- +... +box.space.test3:drop() +--- +... +box.schema.user.revoke('guest', 'write', 'space', '_space') +--- +... +box.schema.user.revoke('guest', 'write', 'space', '_schema') +--- +... +box.schema.user.revoke('guest', 'create', 'universe') +--- +... +c:close() +--- +... +box.schema.func.drop('create_space') +--- +... diff --git a/test/box/net.box_schema_change_gh-2666.test.lua b/test/box/net.box_schema_change_gh-2666.test.lua new file mode 100644 index 000000000..16e28e092 --- /dev/null +++ b/test/box/net.box_schema_change_gh-2666.test.lua @@ -0,0 +1,28 @@ +net = require('net.box') + +-- +-- gh-2666: check that netbox.call is not repeated on schema +-- change. +-- +box.schema.user.grant('guest', 'write', 'space', '_space') +box.schema.user.grant('guest', 'write', 'space', '_schema') +box.schema.user.grant('guest', 'create', 'universe') +count = 0 +function create_space(name) count = count + 1 box.schema.create_space(name) return true end +box.schema.func.create('create_space') +box.schema.user.grant('guest', 'execute', 'function', 'create_space') +c = net.connect(box.cfg.listen) +c:call('create_space', {'test1'}) +count +c:call('create_space', {'test2'}) +count +c:call('create_space', {'test3'}) +count +box.space.test1:drop() +box.space.test2:drop() +box.space.test3:drop() +box.schema.user.revoke('guest', 'write', 'space', '_space') +box.schema.user.revoke('guest', 'write', 'space', '_schema') +box.schema.user.revoke('guest', 'create', 'universe') +c:close() +box.schema.func.drop('create_space') diff --git a/test/box/net.box_schema_change_gh-3107.result b/test/box/net.box_schema_change_gh-3107.result new file mode 100644 index 000000000..233c83307 --- /dev/null +++ b/test/box/net.box_schema_change_gh-3107.result @@ -0,0 +1,151 @@ +fiber = require 'fiber' +--- +... +net = require('net.box') +--- +... +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +--- +... +box.schema.func.create('long_function') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +--- +... +function long_function(...) cond = fiber.cond() cond:wait() return ... end +--- +... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +--- +... +s = box.schema.create_space('test') +--- +... +pk = s:create_index('pk') +--- +... +s:replace{1} +--- +- [1] +... +s:replace{2} +--- +- [2] +... +s:replace{3} +--- +- [3] +... +s:replace{4} +--- +- [4] +... +c = net:connect(box.cfg.listen) +--- +... +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +--- +... +ret = {} +--- +... +count = 0 +--- +... +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +--- +... +future:wait_result(0.01) -- Must fail on timeout. +--- +- null +- Timeout exceeded +... +finalize_long() +--- +... +while count ~= 10 do fiber.sleep(0.1) end +--- +... +ret +--- +- - &0 [1, 2, 3] + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 + - *0 +... +box.schema.func.drop('long_function') +--- +... +-- +-- Test async schema version change. +-- +function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end +--- +... +box.schema.func.create('change_schema') +--- +... +box.schema.user.grant('guest', 'execute', 'function', 'change_schema') +--- +... +box.schema.user.grant('guest', 'write', 'space', '_schema') +--- +... +box.schema.user.grant('guest', 'read,write', 'space', '_space') +--- +... +box.schema.user.grant('guest', 'create', 'space') +--- +... +future1 = c:call('change_schema', {'1'}, {is_async = true}) +--- +... +future2 = c:call('change_schema', {'2'}, {is_async = true}) +--- +... +future3 = c:call('change_schema', {'3'}, {is_async = true}) +--- +... +future1:wait_result() +--- +- ['ok'] +... +future2:wait_result() +--- +- ['ok'] +... +future3:wait_result() +--- +- ['ok'] +... +c:close() +--- +... +s:drop() +--- +... +box.schema.func.drop('change_schema') +--- +... +box.schema.user.revoke('guest', 'write', 'space', '_schema') +--- +... +box.schema.user.revoke('guest', 'read,write', 'space', '_space') +--- +... +box.schema.user.revoke('guest', 'create', 'space') +--- +... diff --git a/test/box/net.box_schema_change_gh-3107.test.lua b/test/box/net.box_schema_change_gh-3107.test.lua new file mode 100644 index 000000000..c73788455 --- /dev/null +++ b/test/box/net.box_schema_change_gh-3107.test.lua @@ -0,0 +1,55 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Ensure a request can be finalized from non-caller fibers. +-- +future = c:call('long_function', {1, 2, 3}, {is_async = true}) +ret = {} +count = 0 +for i = 1, 10 do fiber.create(function() ret[i] = future:wait_result(1000) count = count + 1 end) end +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +while count ~= 10 do fiber.sleep(0.1) end +ret + +box.schema.func.drop('long_function') + +-- +-- Test async schema version change. +-- +function change_schema(i) local tmp = box.schema.create_space('test'..i) return 'ok' end +box.schema.func.create('change_schema') +box.schema.user.grant('guest', 'execute', 'function', 'change_schema') +box.schema.user.grant('guest', 'write', 'space', '_schema') +box.schema.user.grant('guest', 'read,write', 'space', '_space') +box.schema.user.grant('guest', 'create', 'space') +future1 = c:call('change_schema', {'1'}, {is_async = true}) +future2 = c:call('change_schema', {'2'}, {is_async = true}) +future3 = c:call('change_schema', {'3'}, {is_async = true}) +future1:wait_result() +future2:wait_result() +future3:wait_result() + +c:close() +s:drop() +box.schema.func.drop('change_schema') +box.schema.user.revoke('guest', 'write', 'space', '_schema') +box.schema.user.revoke('guest', 'read,write', 'space', '_space') +box.schema.user.revoke('guest', 'create', 'space') diff --git a/test/box/net.box_session_type_gh-2642.result b/test/box/net.box_session_type_gh-2642.result new file mode 100644 index 000000000..0e043f6e5 --- /dev/null +++ b/test/box/net.box_session_type_gh-2642.result @@ -0,0 +1,22 @@ +net = require('net.box') +--- +... +-- +-- gh-2642: box.session.type() +-- +box.schema.user.grant('guest','execute','universe') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:call("box.session.type") +--- +- binary +... +c:close() +--- +... +box.schema.user.revoke('guest', 'execute', 'universe') +--- +... diff --git a/test/box/net.box_session_type_gh-2642.test.lua b/test/box/net.box_session_type_gh-2642.test.lua new file mode 100644 index 000000000..4e3cf5265 --- /dev/null +++ b/test/box/net.box_session_type_gh-2642.test.lua @@ -0,0 +1,11 @@ +net = require('net.box') + +-- +-- gh-2642: box.session.type() +-- + +box.schema.user.grant('guest','execute','universe') +c = net.connect(box.cfg.listen) +c:call("box.session.type") +c:close() +box.schema.user.revoke('guest', 'execute', 'universe') diff --git a/test/box/net.box_space_format_gh-2402.result b/test/box/net.box_space_format_gh-2402.result new file mode 100644 index 000000000..c66665c73 --- /dev/null +++ b/test/box/net.box_space_format_gh-2402.result @@ -0,0 +1,49 @@ +net = require('net.box') +--- +... +-- +-- gh-2402 net.box doesn't support space:format() +-- +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +--- +... +space ~= nil +--- +- true +... +_ = box.space.test:create_index('primary') +--- +... +box.schema.user.grant('guest', 'read', 'space', 'test') +--- +... +c = net.connect(box.cfg.listen) +--- +... +c:ping() +--- +- true +... +c.space.test ~= nil +--- +- true +... +format = c.space.test:format() +--- +... +format[1] ~= nil +--- +- true +... +format[1].name == "id" +--- +- true +... +format[1].type == "unsigned" +--- +- true +... +c.space.test:format({}) +--- +- error: net.box does not support setting space format +... diff --git a/test/box/net.box_space_format_gh-2402.test.lua b/test/box/net.box_space_format_gh-2402.test.lua new file mode 100644 index 000000000..020f20da6 --- /dev/null +++ b/test/box/net.box_space_format_gh-2402.test.lua @@ -0,0 +1,23 @@ +net = require('net.box') + +-- +-- gh-2402 net.box doesn't support space:format() +-- + +space = box.schema.space.create('test', {format={{name="id", type="unsigned"}}}) +space ~= nil +_ = box.space.test:create_index('primary') +box.schema.user.grant('guest', 'read', 'space', 'test') + +c = net.connect(box.cfg.listen) + +c:ping() +c.space.test ~= nil + +format = c.space.test:format() + +format[1] ~= nil +format[1].name == "id" +format[1].type == "unsigned" + +c.space.test:format({}) diff --git a/test/box/net.box_timeout-gh-3107.result b/test/box/net.box_timeout-gh-3107.result new file mode 100644 index 000000000..be7f9606c --- /dev/null +++ b/test/box/net.box_timeout-gh-3107.result @@ -0,0 +1,125 @@ +-- test-run result file version 2 +fiber = require 'fiber' + | --- + | ... +net = require('net.box') + | --- + | ... + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil + | --- + | ... +box.schema.func.create('long_function') + | --- + | ... +box.schema.user.grant('guest', 'execute', 'function', 'long_function') + | --- + | ... +function long_function(...) cond = fiber.cond() cond:wait() return ... end + | --- + | ... +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end + | --- + | ... +s = box.schema.create_space('test') + | --- + | ... +pk = s:create_index('pk') + | --- + | ... +s:replace{1} + | --- + | - [1] + | ... +s:replace{2} + | --- + | - [2] + | ... +s:replace{3} + | --- + | - [3] + | ... +s:replace{4} + | --- + | - [4] + | ... +c = net:connect(box.cfg.listen) + | --- + | ... + +-- +-- Check infinity timeout. +-- +ret = nil + | --- + | ... +_ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async = true}):wait_result() end) + | --- + | ... +finalize_long() + | --- + | ... +while not ret do fiber.sleep(0.01) end + | --- + | ... +ret + | --- + | - [1, 2, 3] + | ... +c:close() + | --- + | ... +box.schema.user.grant('guest', 'execute', 'universe') + | --- + | ... +c = net:connect(box.cfg.listen) + | --- + | ... +future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true}) + | --- + | ... +future:result() + | --- + | - null + | - Response is not ready + | ... +future:wait_result(0.01) -- Must fail on timeout. + | --- + | - null + | - Timeout exceeded + | ... +finalize_long() + | --- + | ... +future:wait_result(100) + | --- + | - [1, 2, 3] + | ... + +c:close() + | --- + | ... +-- +-- Check that is_async does not work on a closed connection. +-- +c:call('any_func', {}, {is_async = true}) + | --- + | - error: Connection closed + | ... + +box.schema.user.revoke('guest', 'execute', 'universe') + | --- + | ... +c = net:connect(box.cfg.listen) + | --- + | ... + +c:close() + | --- + | ... +s:drop() + | --- + | ... diff --git a/test/box/net.box_timeout-gh-3107.test.lua b/test/box/net.box_timeout-gh-3107.test.lua new file mode 100644 index 000000000..08fa039db --- /dev/null +++ b/test/box/net.box_timeout-gh-3107.test.lua @@ -0,0 +1,47 @@ +fiber = require 'fiber' +net = require('net.box') + +-- +-- gh-3107: fiber-async netbox. +-- +cond = nil +box.schema.func.create('long_function') +box.schema.user.grant('guest', 'execute', 'function', 'long_function') +function long_function(...) cond = fiber.cond() cond:wait() return ... end +function finalize_long() while not cond do fiber.sleep(0.01) end cond:signal() cond = nil end +s = box.schema.create_space('test') +pk = s:create_index('pk') +s:replace{1} +s:replace{2} +s:replace{3} +s:replace{4} +c = net:connect(box.cfg.listen) + +-- +-- Check infinity timeout. +-- +ret = nil +_ = fiber.create(function() ret = c:call('long_function', {1, 2, 3}, {is_async = true}):wait_result() end) +finalize_long() +while not ret do fiber.sleep(0.01) end +ret +c:close() +box.schema.user.grant('guest', 'execute', 'universe') +c = net:connect(box.cfg.listen) +future = c:eval('return long_function(...)', {1, 2, 3}, {is_async = true}) +future:result() +future:wait_result(0.01) -- Must fail on timeout. +finalize_long() +future:wait_result(100) + +c:close() +-- +-- Check that is_async does not work on a closed connection. +-- +c:call('any_func', {}, {is_async = true}) + +box.schema.user.revoke('guest', 'execute', 'universe') +c = net:connect(box.cfg.listen) + +c:close() +s:drop() diff --git a/test/box/net.box_timeout_gh-1533.result b/test/box/net.box_timeout_gh-1533.result new file mode 100644 index 000000000..10dccd74f --- /dev/null +++ b/test/box/net.box_timeout_gh-1533.result @@ -0,0 +1,89 @@ +fiber = require 'fiber' +--- +... +test_run = require('test_run').new() +--- +... +net = require('net.box') +--- +... +-- Tarantool < 1.7.1 compatibility (gh-1533) +c = net.new(box.cfg.listen) +--- +... +c:ping() +--- +- true +... +c:close() +--- +... +-- Test for connect_timeout > 0 in netbox connect +test_run:cmd("setopt delimiter ';'"); +--- +- true +... +need_stop = false; +--- +... +greeting = +"Tarantool 1.7.3 (Lua console)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" .. +"type 'help' for interactive help~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; +--- +... +socket = require('socket'); +--- +... +srv = socket.tcp_server('localhost', 0, { + handler = function(fd) + local fiber = require('fiber') + while not need_stop do + fiber.sleep(0.01) + end + fd:write(greeting) + end +}); +--- +... +-- we must get timeout +port = srv:name().port +nb = net.new('localhost:' .. port, { + wait_connected = true, console = true, + connect_timeout = 0.1 +}); +--- +... +nb.error:find('timed out') ~= nil; +--- +- true +... +need_stop = true +nb:close(); +--- +... +-- we must get peer closed +nb = net.new('localhost:' .. port, { + wait_connected = true, console = true, + connect_timeout = 0.2 +}); +--- +... +nb.error ~= "Timeout exceeded"; +--- +- true +... +nb:close(); +--- +... +test_run:cmd("setopt delimiter ''"); +--- +- true +... +srv:close() +--- +- true +... +test_run:cmd("clear filter") +--- +- true +... diff --git a/test/box/net.box_timeout_gh-1533.test.lua b/test/box/net.box_timeout_gh-1533.test.lua new file mode 100644 index 000000000..08fddb0bb --- /dev/null +++ b/test/box/net.box_timeout_gh-1533.test.lua @@ -0,0 +1,45 @@ +fiber = require 'fiber' +test_run = require('test_run').new() +net = require('net.box') + +-- Tarantool < 1.7.1 compatibility (gh-1533) +c = net.new(box.cfg.listen) +c:ping() +c:close() + +-- Test for connect_timeout > 0 in netbox connect +test_run:cmd("setopt delimiter ';'"); +need_stop = false; +greeting = +"Tarantool 1.7.3 (Lua console)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" .. +"type 'help' for interactive help~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"; +socket = require('socket'); +srv = socket.tcp_server('localhost', 0, { + handler = function(fd) + local fiber = require('fiber') + while not need_stop do + fiber.sleep(0.01) + end + fd:write(greeting) + end +}); +port = srv:name().port +-- we must get timeout +nb = net.new('localhost:' .. port, { + wait_connected = true, console = true, + connect_timeout = 0.1 +}); +nb.error:find('timed out') ~= nil; +need_stop = true +nb:close(); +-- we must get peer closed +nb = net.new('localhost:' .. port, { + wait_connected = true, console = true, + connect_timeout = 0.2 +}); +nb.error ~= "Timeout exceeded"; +nb:close(); +test_run:cmd("setopt delimiter ''"); +srv:close() + +test_run:cmd("clear filter") diff --git a/test/box/net.box_upsert_gh-970.result b/test/box/net.box_upsert_gh-970.result new file mode 100644 index 000000000..d3ec20c23 --- /dev/null +++ b/test/box/net.box_upsert_gh-970.result @@ -0,0 +1,49 @@ +net = require('net.box') +--- +... +-- gh-970 gh-971 UPSERT over network +_ = box.schema.space.create('test') +--- +... +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) +--- +... +_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) +--- +... +_ = box.space.test:insert{1, 2, "string"} +--- +... +box.schema.user.grant('guest', 'read,write', 'space', 'test') +--- +... +c = net:connect(box.cfg.listen) +--- +... +c.space.test:select{} +--- +- - [1, 2, 'string'] +... +c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update +--- +... +c.space.test:select{} +--- +- - [1, 3, 'string'] +... +c.space.test:upsert({2, 4, 'something'}, {{'+', 2, 1}}) -- insert +--- +... +c.space.test:select{} +--- +- - [1, 3, 'string'] + - [2, 4, 'something'] +... +c.space.test:upsert({2, 4, 'nothing'}, {{'+', 3, 100500}}) -- wrong operation +--- +... +c.space.test:select{} +--- +- - [1, 3, 'string'] + - [2, 4, 'something'] +... diff --git a/test/box/net.box_upsert_gh-970.test.lua b/test/box/net.box_upsert_gh-970.test.lua new file mode 100644 index 000000000..0ea9092eb --- /dev/null +++ b/test/box/net.box_upsert_gh-970.test.lua @@ -0,0 +1,16 @@ +net = require('net.box') + +-- gh-970 gh-971 UPSERT over network +_ = box.schema.space.create('test') +_ = box.space.test:create_index('primary', {type = 'TREE', parts = {1,'unsigned'}}) +_ = box.space.test:create_index('covering', {type = 'TREE', parts = {1,'unsigned',3,'string',2,'unsigned'}}) +_ = box.space.test:insert{1, 2, "string"} +box.schema.user.grant('guest', 'read,write', 'space', 'test') +c = net:connect(box.cfg.listen) +c.space.test:select{} +c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update +c.space.test:select{} +c.space.test:upsert({2, 4, 'something'}, {{'+', 2, 1}}) -- insert +c.space.test:select{} +c.space.test:upsert({2, 4, 'nothing'}, {{'+', 3, 100500}}) -- wrong operation +c.space.test:select{} diff --git a/test/box/net.box_wait_connected_gh-3856.result b/test/box/net.box_wait_connected_gh-3856.result new file mode 100644 index 000000000..9234e6cb9 --- /dev/null +++ b/test/box/net.box_wait_connected_gh-3856.result @@ -0,0 +1,20 @@ +net = require('net.box') +--- +... +-- +-- gh-3856: wait_connected = false is ignored. +-- +c = net.connect('8.8.8.8:123456', {wait_connected = false}) +--- +... +c +--- +- opts: + wait_connected: false + host: 8.8.8.8 + state: initial + port: '123456' +... +c:close() +--- +... diff --git a/test/box/net.box_wait_connected_gh-3856.test.lua b/test/box/net.box_wait_connected_gh-3856.test.lua new file mode 100644 index 000000000..29e997fb5 --- /dev/null +++ b/test/box/net.box_wait_connected_gh-3856.test.lua @@ -0,0 +1,8 @@ +net = require('net.box') + +-- +-- gh-3856: wait_connected = false is ignored. +-- +c = net.connect('8.8.8.8:123456', {wait_connected = false}) +c +c:close() -- 2.17.1