[Tarantool-patches] [PATCH v1] Divide test box/net.box

Sergey Bronnikov sergeyb at tarantool.org
Thu Apr 2 18:44:44 MSK 2020


Hello!

before splitting test we had a net.box.skipcond file due to an issue
https://github.com/tarantool/tarantool/issues/4271. I believe that file
is useless now and we should add similar files for a new tests.

I have looked on tests without postfix "gh-xxx" in a filenames.
LGTM for them:

net.box_connect_triggers.test.lua
net.box_permissions.test.lua
net.box_reconnect_after.test.lua
net.box_get_connection_object.test.lua

I propose to run tests with postfix "gh-xxx" in filenames on commits
before fix where bug covered by test was added. Broken test would mean
it still works.

Sergey

On 09:38 Thu 02 Apr , Alexander V. Tikhonov wrote:
> 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...\"]:<line>: '")
> ----
> -- 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..."]:<line>: 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..."]:<line>: 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..."]:<line>: 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..."]:<line>: index:get() doesn''t support `buffer` argument'
> -...
> -c.space.test.index.primary:min({}, { buffer = ibuf})
> ----
> -- error: 'builtin/box/net_box.lua..."]:<line>: index:min() doesn''t support `buffer` argument'
> -...
> -c.space.test.index.primary:max({}, { buffer = ibuf})
> ----
> -- error: 'builtin/box/net_box.lua..."]:<line>: index:max() doesn''t support `buffer` argument'
> -...
> -c.space.test.index.primary:count({}, { buffer = ibuf})
> ----
> -- error: 'builtin/box/net_box.lua..."]:<line>: index:count() doesn''t support `buffer` argument'
> -...
> -c.space.test.index.primary:get({1}, { buffer = ibuf})
> ----
> -- error: 'builtin/box/net_box.lua..."]:<line>: 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...\"]:<line>: '")
> -
> -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...\"]:<line>: '")
> +---
> +- 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..."]:<line>: 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..."]:<line>: 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...\"]:<line>: '")
> +
> +_ = 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...\"]:<line>: '")
> +---
> +- 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..."]:<line>: 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...\"]:<line>: '")
> +
> +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...\"]:<line>: '")
> +---
> +- 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..."]:<line>: 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..."]:<line>: 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..."]:<line>: index:get() doesn''t support `buffer` argument'
> +...
> +c.space.test.index.primary:min({}, { buffer = ibuf})
> +---
> +- error: 'builtin/box/net_box.lua..."]:<line>: index:min() doesn''t support `buffer` argument'
> +...
> +c.space.test.index.primary:max({}, { buffer = ibuf})
> +---
> +- error: 'builtin/box/net_box.lua..."]:<line>: index:max() doesn''t support `buffer` argument'
> +...
> +c.space.test.index.primary:count({}, { buffer = ibuf})
> +---
> +- error: 'builtin/box/net_box.lua..."]:<line>: index:count() doesn''t support `buffer` argument'
> +...
> +c.space.test.index.primary:get({1}, { buffer = ibuf})
> +---
> +- error: 'builtin/box/net_box.lua..."]:<line>: 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...\"]:<line>: '")
> +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
> 

-- 
sergeyb@


More information about the Tarantool-patches mailing list