From bf06417a563af731f241afedd805e66626192eff Mon Sep 17 00:00:00 2001
From: Georgy Moshkin <gmoshkin@picodata.io>
Date: Wed, 26 Jul 2023 13:34:01 +0300
Subject: [PATCH] feat: make opts.timeout optional in lua api

---
 CHANGELOG.md         |   5 +-
 src/luamod.lua       |  62 +++++++++++----------
 src/luamod.rs        |  31 ++++++-----
 src/util.rs          |  13 ++++-
 test/int/test_acl.py | 130 ++++++++++++++-----------------------------
 5 files changed, 108 insertions(+), 133 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 396e7cc37a..bbe5c9419a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -42,7 +42,7 @@ with the `YY.0M.MICRO` scheme.
 ### Lua API:
 
 
-- Update `pico.LUA_API_VERSION`: `1.0.0` -> `2.0.0`
+- Update `pico.LUA_API_VERSION`: `1.0.0` -> `2.1.0`
 - New semantics of `pico.create_space()`. It's idempotent now.
 - Add `pico.drop_space()`
 - Add `pico.create_user()`, `pico.drop_user()`
@@ -51,7 +51,8 @@ with the `YY.0M.MICRO` scheme.
 - Add `pico.raft_term()`
 - Add `pico.change_password()`
 - Add `pico.wait_ddl_finalize()`
-- Changed `pico.raft_log()` options.
+- Change `pico.raft_log()` arguments
+- Make `opts.timeout` optional in most functions
 
 ## [23.06.0] - 2023-06-16
 
diff --git a/src/luamod.lua b/src/luamod.lua
index d4ebab8e07..4be9f726c8 100644
--- a/src/luamod.lua
+++ b/src/luamod.lua
@@ -47,6 +47,8 @@ function pico.help(topic)
     end
 end
 
+local TIMEOUT_INFINITY = 100 * 365 * 24 * 60 * 60
+
 local function mandatory_param(value, name)
     if value == nil then
         box.error(box.error.ILLEGAL_PARAMS, name .. ' is mandatory')
@@ -194,9 +196,10 @@ Params:
 
     1. user (string), username
     2. password (string)
-    3. opts (table)
-        - timeout (number), seconds
-        - auth_type (string)
+    3. opts (optional table)
+        - auth_type (optional string), authentication method name,
+            defaults to box.cfg.auth_type value
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -215,7 +218,7 @@ function pico.create_user(user, password, opts)
         })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
@@ -280,9 +283,10 @@ Params:
 
     1. user (string), username
     2. password (string)
-    3. opts (table)
-        - timeout (number), seconds
-        - auth_type (string)
+    3. opts (optional table)
+        - auth_type (optional string), authentication method name,
+            defaults to box.cfg.auth_type value
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -300,7 +304,7 @@ function pico.change_password(user, password, opts)
         })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
@@ -362,8 +366,8 @@ result.
 Params:
 
     1. user (string), username
-    2. opts (table)
-        - timeout (number), seconds
+    2. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -377,7 +381,7 @@ function pico.drop_user(user, opts)
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
@@ -427,8 +431,8 @@ result.
 Params:
 
     1. name (string), role name
-    2. opts (table)
-        - timeout (number), seconds
+    2. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -442,7 +446,7 @@ function pico.create_role(role, opts)
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
@@ -498,8 +502,8 @@ result.
 Params:
 
     1. role (string), role name
-    2. opts (table)
-        - timeout (number), seconds
+    2. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -513,7 +517,7 @@ function pico.drop_role(role, opts)
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
@@ -736,8 +740,8 @@ Params:
     4. object_name (optional string), can be omitted when privilege concerns an
         entire class of entities, see examples below.
 
-    5. opts (table)
-        - timeout (number), seconds
+    5. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -777,7 +781,7 @@ function pico.grant_privilege(grantee, privilege, object_type, object_name, opts
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
 
         privilege_check(privilege, object_type, 'grant_privilege')
@@ -857,8 +861,8 @@ Params:
     4. object_name (optional string), can be omitted when privilege concerns an
         entire class of entities, see pico.help("pico.grant_privilege") for details.
 
-    5. opts (table)
-        - timeout (number), seconds
+    5. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -876,7 +880,7 @@ function pico.revoke_privilege(grantee, privilege, object_type, object_name, opt
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
 
         privilege_check(privilege, object_type, 'revoke_privilege')
@@ -958,7 +962,7 @@ Params:
         - by_field (optional string), usually 'bucket_id'
         - sharding_key (optional table {string,...}) with field names
         - sharding_fn (optional string), only default 'murmur3' is supported for now
-        - timeout (number), in seconds
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -1035,7 +1039,9 @@ function pico.create_space(opts)
         mandatory_param(opts.format, 'opts.format')
         mandatory_param(opts.primary_key, 'opts.primary_key')
         mandatory_param(opts.distribution, 'opts.distribution')
-        mandatory_param(opts.timeout, 'opts.timeout')
+        if not opts.timeout then
+            opts.timeout = TIMEOUT_INFINITY
+        end
 
         local ok, err = pico._check_create_space_opts(opts)
         if not ok then
@@ -1105,8 +1111,8 @@ Params:
 
     1. space (number | string), clusterwide space id or name
 
-    2. opts (table)
-        - timeout (number), seconds
+    2. opts (optional table)
+        - timeout (optional number), in seconds, default: infinity
 
 Returns:
 
@@ -1122,7 +1128,7 @@ function pico.drop_space(space, opts)
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
         if not opts.timeout then
-            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+            opts.timeout = TIMEOUT_INFINITY
         end
     end)
     if not ok then
diff --git a/src/luamod.rs b/src/luamod.rs
index 456e4d58fa..fae56fc01f 100644
--- a/src/luamod.rs
+++ b/src/luamod.rs
@@ -11,6 +11,7 @@ use crate::traft::op::{self, Op};
 use crate::traft::{self, node, RaftIndex, RaftTerm};
 use crate::util::duration_from_secs_f64_clamped;
 use crate::util::str_eq;
+use crate::util::INFINITY;
 use crate::{args, rpc, sync, tlog};
 use ::tarantool::fiber;
 use ::tarantool::tlua;
@@ -87,10 +88,10 @@ pub(crate) fn setup(args: &args::Run) {
 
             picodata> pico.LUA_API_VERSION
             ---
-            - 2.0.0
+            - 2.1.0
             ...
         "},
-        "2.0.0",
+        "2.1.0",
     );
 
     luamod_set(
@@ -286,7 +287,7 @@ pub(crate) fn setup(args: &args::Run) {
 
         Params:
 
-            1. timeout (number), in seconds
+            1. n_times (number)
 
         Returns:
 
@@ -1273,7 +1274,7 @@ pub(crate) fn setup(args: &args::Run) {
         &l,
         "abort_ddl",
         indoc! {"
-        pico.abort_ddl(timeout)
+        pico.abort_ddl([timeout])
         =======================
 
         Aborts a pending schema change.
@@ -1283,7 +1284,7 @@ pub(crate) fn setup(args: &args::Run) {
 
         Params:
 
-            1. timeout (number), in seconds
+            1. timeout (optional number), in seconds, default: infinity
 
         Returns:
 
@@ -1292,8 +1293,13 @@ pub(crate) fn setup(args: &args::Run) {
             (nil, string) in case of an error
         "},
         {
-            tlua::function1(|timeout: f64| -> traft::Result<RaftIndex> {
-                schema::abort_ddl(duration_from_secs_f64_clamped(timeout))
+            tlua::function1(|timeout: Option<f64>| -> traft::Result<RaftIndex> {
+                let timeout = if let Some(timeout) = timeout {
+                    duration_from_secs_f64_clamped(timeout)
+                } else {
+                    INFINITY
+                };
+                schema::abort_ddl(timeout)
             })
         },
     );
@@ -1301,7 +1307,7 @@ pub(crate) fn setup(args: &args::Run) {
         &l,
         "wait_ddl_finalize",
         indoc! {"
-        pico.wait_ddl_finalize(index, opts)
+        pico.wait_ddl_finalize(index, [opts])
         =======================
 
         Waits for the ddl operation at given raft index to be finalized.
@@ -1311,8 +1317,8 @@ pub(crate) fn setup(args: &args::Run) {
         Params:
 
             1. index (number), raft index
-            1. opts (table)
-                - timeout (number), in seconds, default: 3 seconds
+            2. opts (optional table)
+                - timeout (optional number), in seconds, default: infinity
 
         Returns:
 
@@ -1327,13 +1333,12 @@ pub(crate) fn setup(args: &args::Run) {
             }
             tlua::Function::new(
                 |index: RaftIndex, opts: Option<Opts>| -> traft::Result<RaftIndex> {
-                    let mut timeout = 3.0;
+                    let mut timeout = INFINITY;
                     if let Some(opts) = opts {
                         if let Some(t) = opts.timeout {
-                            timeout = t;
+                            timeout = duration_from_secs_f64_clamped(t);
                         }
                     }
-                    let timeout = duration_from_secs_f64_clamped(timeout);
                     let commit_index = schema::wait_for_ddl_commit(index, timeout)?;
                     Ok(commit_index)
                 },
diff --git a/src/util.rs b/src/util.rs
index b4d71f134f..1df90ebc93 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -12,12 +12,19 @@ pub use Either::{Left, Right};
 pub const INFINITY: Duration = Duration::from_secs(30 * 365 * 24 * 60 * 60);
 
 /// Converts `secs` to `Duration`. If `secs` is negative, it's clamped to zero.
+/// If `secs` overflows the `Duration` it's clamped to [`INFINITY`].
+///
+/// Panics if `secs` is NaN.
 #[inline(always)]
 pub fn duration_from_secs_f64_clamped(secs: f64) -> Duration {
-    if secs > 0.0 {
-        Duration::from_secs_f64(secs)
-    } else {
+    if secs <= 0.0 {
         Duration::ZERO
+    } else if secs.is_nan() {
+        panic!("attempt to construct a Duration from NaN of seconds");
+    } else if let Ok(d) = Duration::try_from_secs_f64(secs) {
+        d
+    } else {
+        INFINITY
     }
 }
 
diff --git a/test/int/test_acl.py b/test/int/test_acl.py
index 22f30ff7f6..3d35f23ea3 100644
--- a/test/int/test_acl.py
+++ b/test/int/test_acl.py
@@ -19,29 +19,29 @@ def test_acl_lua_api(cluster: Cluster):
         i1.call("pico.create_user", "Dave")
 
     # This is probably not ok.
-    i1.call("pico.create_user", "Dave", "", dict(timeout=3))
+    i1.call("pico.create_user", "Dave", "")
 
     # Already exists -> ok.
-    i1.call("pico.create_user", "Dave", "", dict(timeout=3))
+    i1.call("pico.create_user", "Dave", "")
 
     # FIXME
     # Already exists but with different parameters -> should fail,
     # but doesn't currently.
-    i1.call("pico.create_user", "Dave", "different password", dict(timeout=3))
+    i1.call("pico.create_user", "Dave", "different password")
 
     # Role already exists -> error.
     with pytest.raises(ReturnError, match="Role 'super' already exists"):
-        i1.call("pico.create_user", "super", "", dict(timeout=3))
+        i1.call("pico.create_user", "super", "")
 
     #
     # pico.change_password
     #
 
     # Change password -> ok.
-    i1.call("pico.change_password", "Dave", "no-one-will-know", dict(timeout=3))
+    i1.call("pico.change_password", "Dave", "no-one-will-know")
 
     # Change password to the sameone -> ok.
-    i1.call("pico.change_password", "Dave", "no-one-will-know", dict(timeout=3))
+    i1.call("pico.change_password", "Dave", "no-one-will-know")
 
     # No such user -> error.
     with pytest.raises(ReturnError, match="User 'User is not found' is not found"):
@@ -49,7 +49,6 @@ def test_acl_lua_api(cluster: Cluster):
             "pico.change_password",
             "User is not found",
             "password",
-            dict(timeout=3),
         )
 
     #
@@ -61,14 +60,14 @@ def test_acl_lua_api(cluster: Cluster):
         i1.call("pico.create_role")
 
     # Ok.
-    i1.call("pico.create_role", "Parent", dict(timeout=3))
+    i1.call("pico.create_role", "Parent")
 
     # Already exists -> ok.
-    i1.call("pico.create_role", "Parent", dict(timeout=3))
+    i1.call("pico.create_role", "Parent")
 
     # User already exists -> error.
     with pytest.raises(ReturnError, match="User 'Dave' already exists"):
-        i1.call("pico.create_role", "Dave", dict(timeout=3))
+        i1.call("pico.create_role", "Dave")
 
     #
     # pico.grant_privilege / pico.revoke_privilege parameter verification
@@ -91,7 +90,6 @@ def test_acl_lua_api(cluster: Cluster):
                 "execute",
                 "universe",
                 None,
-                dict(timeout=3),
             )
 
         # No such privilege -> error.
@@ -99,16 +97,14 @@ def test_acl_lua_api(cluster: Cluster):
             ReturnError,
             match=rf"unsupported privilege 'boogie', see pico.help\('{f}'\) for details",
         ):
-            i1.call(f"pico.{f}", "Dave", "boogie", "universe", None, dict(timeout=3))
+            i1.call(f"pico.{f}", "Dave", "boogie", "universe", None)
 
         # Comma separated list of privileges -> error.
         with pytest.raises(
             ReturnError,
             match=rf"unsupported privilege 'read,write', see pico.help\('{f}'\) for details",
         ):
-            i1.call(
-                f"pico.{f}", "Dave", "read,write", "universe", None, dict(timeout=3)
-            )
+            i1.call(f"pico.{f}", "Dave", "read,write", "universe", None)
 
         # No object_type -> error.
         with pytest.raises(ReturnError, match="object_type should be a string"):
@@ -116,15 +112,15 @@ def test_acl_lua_api(cluster: Cluster):
 
         # No such object_type -> error.
         with pytest.raises(ReturnError, match="Unknown object type 'bible'"):
-            i1.call(f"pico.{f}", "Dave", "read", "bible", None, dict(timeout=3))
+            i1.call(f"pico.{f}", "Dave", "read", "bible", None)
 
         # Wrong combo -> error.
         with pytest.raises(ReturnError, match="Unsupported space privilege 'grant'"):
-            i1.call(f"pico.{f}", "Dave", "grant", "space", None, dict(timeout=3))
+            i1.call(f"pico.{f}", "Dave", "grant", "space", None)
 
         # No such role -> error.
         with pytest.raises(ReturnError, match="Role 'Joker' is not found"):
-            i1.call(f"pico.{f}", "Dave", "execute", "role", "Joker", dict(timeout=3))
+            i1.call(f"pico.{f}", "Dave", "execute", "role", "Joker")
 
     #
     # pico.grant_privilege semantics verification
@@ -137,7 +133,6 @@ def test_acl_lua_api(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Already granted -> ok.
@@ -147,7 +142,6 @@ def test_acl_lua_api(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Grant privilege to role -> Ok.
@@ -157,7 +151,6 @@ def test_acl_lua_api(cluster: Cluster):
         "write",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Already granted -> ok.
@@ -167,18 +160,13 @@ def test_acl_lua_api(cluster: Cluster):
         "write",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Assign role to user -> Ok.
-    i1.call(
-        "pico.grant_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3)
-    )
+    i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent")
 
     # Already assigned role to user -> error.
-    i1.call(
-        "pico.grant_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3)
-    )
+    i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent")
 
     #
     # pico.revoke_privilege semantics verification
@@ -191,7 +179,6 @@ def test_acl_lua_api(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Already revoked -> ok.
@@ -201,7 +188,6 @@ def test_acl_lua_api(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Revoke privilege to role -> Ok.
@@ -211,7 +197,6 @@ def test_acl_lua_api(cluster: Cluster):
         "write",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Already revoked -> ok.
@@ -221,13 +206,10 @@ def test_acl_lua_api(cluster: Cluster):
         "write",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
 
     # Revoke role to user -> Ok.
-    i1.call(
-        "pico.revoke_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3)
-    )
+    i1.call("pico.revoke_privilege", "Dave", "execute", "role", "Parent")
 
     # Already revoked role to user -> ok.
     i1.call(
@@ -236,7 +218,6 @@ def test_acl_lua_api(cluster: Cluster):
         "execute",
         "role",
         "Parent",
-        dict(timeout=3),
     )
 
     #
@@ -245,16 +226,16 @@ def test_acl_lua_api(cluster: Cluster):
 
     # No user -> error.
     with pytest.raises(ReturnError, match="user should be a string"):
-        i1.call("pico.drop_user", dict(timeout=3))
+        i1.call("pico.drop_user")
 
     # No such user -> ok.
-    i1.call("pico.drop_user", "User is not found", dict(timeout=3))
+    i1.call("pico.drop_user", "User is not found")
 
     # Ok.
-    i1.call("pico.drop_user", "Dave", dict(timeout=3))
+    i1.call("pico.drop_user", "Dave")
 
     # Repeat drop -> ok.
-    i1.call("pico.drop_user", "Dave", dict(timeout=3))
+    i1.call("pico.drop_user", "Dave")
 
     #
     # pico.drop_role
@@ -265,13 +246,13 @@ def test_acl_lua_api(cluster: Cluster):
         i1.call("pico.drop_role")
 
     # No such role -> ok.
-    i1.call("pico.drop_role", "Role is not found", dict(timeout=3))
+    i1.call("pico.drop_role", "Role is not found")
 
     # Ok.
-    i1.call("pico.drop_role", "Parent", dict(timeout=3))
+    i1.call("pico.drop_role", "Parent")
 
     # Repeat drop -> ok.
-    i1.call("pico.drop_role", "Parent", dict(timeout=3))
+    i1.call("pico.drop_role", "Parent")
 
     #
     # Options validation
@@ -291,10 +272,6 @@ def test_acl_lua_api(cluster: Cluster):
     ):
         i1.call("pico.create_user", "Dave", "pass", dict(timeout="3s"))
 
-    # No timeout -> error.
-    with pytest.raises(ReturnError, match="opts.timeout is mandatory"):
-        i1.call("pico.create_user", "Dave", "pass")
-
 
 def test_acl_basic(cluster: Cluster):
     i1, *_ = cluster.deploy(instance_count=4, init_replication_factor=2)
@@ -311,7 +288,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Create user.
-    index = i1.call("pico.create_user", user, password, dict(timeout=3))
+    index = i1.call("pico.create_user", user, password)
     cluster.raft_wait_index(index)
     v += 1
 
@@ -346,15 +323,11 @@ def test_acl_basic(cluster: Cluster):
     # Grant some privileges.
     # Doing anything via remote function execution requires execute access
     # to the "universe"
-    index = i1.call(
-        "pico.grant_privilege", user, "execute", "universe", None, dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", user, "execute", "universe", None)
     cluster.raft_wait_index(index)
     v += 1
 
-    index = i1.call(
-        "pico.grant_privilege", user, "read", "space", "money", dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", user, "read", "space", "money")
     cluster.raft_wait_index(index)
     v += 1
 
@@ -400,9 +373,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Revoke the privilege.
-    index = i1.call(
-        "pico.revoke_privilege", user, "read", "space", "money", dict(timeout=3)
-    )
+    index = i1.call("pico.revoke_privilege", user, "read", "space", "money")
     cluster.raft_wait_index(index)
     v += 1
 
@@ -419,7 +390,7 @@ def test_acl_basic(cluster: Cluster):
     # Change user's password.
     old_password = password
     new_password = "$3kr3T"
-    index = i1.call("pico.change_password", user, new_password, dict(timeout=3))
+    index = i1.call("pico.change_password", user, new_password)
     cluster.raft_wait_index(index)
     v += 1
 
@@ -437,7 +408,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Drop user.
-    index = i1.call("pico.drop_user", user, dict(timeout=3))
+    index = i1.call("pico.drop_user", user)
 
     for i in cluster.instances:
         i.raft_wait_index(index)
@@ -472,14 +443,12 @@ def test_acl_roles_basic(cluster: Cluster):
     password = "1234"
 
     # Create user.
-    index = i1.call("pico.create_user", user, password, dict(timeout=3))
+    index = i1.call("pico.create_user", user, password)
     cluster.raft_wait_index(index)
 
     # Doing anything via remote function execution requires execute access
     # to the "universe"
-    index = i1.call(
-        "pico.grant_privilege", user, "execute", "universe", None, dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", user, "execute", "universe", None)
     cluster.raft_wait_index(index)
 
     # Try reading from space on behalf of the user.
@@ -494,19 +463,15 @@ def test_acl_roles_basic(cluster: Cluster):
     #
     # Create role.
     role = "PropertyReader"
-    index = i1.call("pico.create_role", role, dict(timeout=3))
+    index = i1.call("pico.create_role", role)
     cluster.raft_wait_index(index)
 
     # Grant the role read access.
-    index = i1.call(
-        "pico.grant_privilege", role, "read", "space", "_pico_property", dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", role, "read", "space", "_pico_property")
     cluster.raft_wait_index(index)
 
     # Assign role to user.
-    index = i1.call(
-        "pico.grant_privilege", user, "execute", "role", role, dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", user, "execute", "role", role)
     cluster.raft_wait_index(index)
 
     # Try reading from space on behalf of the user again. Now succeed.
@@ -521,7 +486,6 @@ def test_acl_roles_basic(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
     cluster.raft_wait_index(index)
 
@@ -534,7 +498,7 @@ def test_acl_roles_basic(cluster: Cluster):
             i.call("box.space._pico_property:select", user=user, password=password)
 
     # Drop the role.
-    index = i1.call("pico.drop_role", role, dict(timeout=3))
+    index = i1.call("pico.drop_role", role)
     cluster.raft_wait_index(index)
 
     # Nothing changed here.
@@ -560,10 +524,10 @@ def test_acl_from_snapshot(cluster: Cluster):
     #
     # Initial state.
     #
-    index = i1.call("pico.create_user", "Sam", "pass", dict(timeout=3))
+    index = i1.call("pico.create_user", "Sam", "pass")
     cluster.raft_wait_index(index)
 
-    index = i1.call("pico.create_role", "Captain", dict(timeout=3))
+    index = i1.call("pico.create_role", "Captain")
     cluster.raft_wait_index(index)
 
     index = i1.call(
@@ -572,7 +536,6 @@ def test_acl_from_snapshot(cluster: Cluster):
         "read",
         "space",
         "_pico_property",
-        dict(timeout=3),
     )
     cluster.raft_wait_index(index)
 
@@ -582,7 +545,6 @@ def test_acl_from_snapshot(cluster: Cluster):
         "read",
         "space",
         "_pico_space",
-        dict(timeout=3),
     )
     cluster.raft_wait_index(index)
 
@@ -616,10 +578,10 @@ def test_acl_from_snapshot(cluster: Cluster):
     #
     # These changes will arive by snapshot.
     #
-    index = i1.call("pico.drop_user", "Sam", dict(timeout=3))
+    index = i1.call("pico.drop_user", "Sam")
     cluster.raft_wait_index(index)
 
-    index = i1.call("pico.create_user", "Blam", "pass", dict(timeout=3))
+    index = i1.call("pico.create_user", "Blam", "pass")
     cluster.raft_wait_index(index)
 
     index = i1.call(
@@ -628,7 +590,6 @@ def test_acl_from_snapshot(cluster: Cluster):
         "read",
         "space",
         "_pico_space",
-        dict(timeout=3),
     )
     cluster.raft_wait_index(index)
 
@@ -638,21 +599,16 @@ def test_acl_from_snapshot(cluster: Cluster):
         "read",
         "space",
         "_pico_instance",
-        dict(timeout=3),
     )
     cluster.raft_wait_index(index)
 
-    index = i1.call("pico.create_role", "Executor", dict(timeout=3))
+    index = i1.call("pico.create_role", "Executor")
     cluster.raft_wait_index(index)
 
-    index = i1.call(
-        "pico.grant_privilege", "Executor", "execute", "universe", None, dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", "Executor", "execute", "universe", None)
     cluster.raft_wait_index(index)
 
-    index = i1.call(
-        "pico.grant_privilege", "Blam", "execute", "role", "Executor", dict(timeout=3)
-    )
+    index = i1.call("pico.grant_privilege", "Blam", "execute", "role", "Executor")
     cluster.raft_wait_index(index)
 
     # Compact log to trigger snapshot generation.
-- 
GitLab