Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org,
	gorcunov@gmail.com
Subject: [Tarantool-patches]  [PATCH v2 12/11] dRaft
Date: Sat, 19 Sep 2020 17:58:28 +0200	[thread overview]
Message-ID: <5a7cf2f2-1b7c-28be-688f-d604a64d0623@tarantool.org> (raw)
In-Reply-To: <cover.1599693319.git.v.shpilevoy@tarantool.org>

    raft: add tests
    
    Part of #1146

diff --git a/test/replication/raft_basic.result b/test/replication/raft_basic.result
new file mode 100644
index 000000000..cff710e24
--- /dev/null
+++ b/test/replication/raft_basic.result
@@ -0,0 +1,168 @@
+-- test-run result file version 2
+test_run = require('test_run').new()
+ | ---
+ | ...
+--
+-- gh-1146: Raft protocol for automated leader election.
+--
+
+old_raft_election_timeout = box.cfg.raft_election_timeout
+ | ---
+ | ...
+
+-- Raft is turned off by default.
+assert(not box.cfg.raft_is_enabled)
+ | ---
+ | - true
+ | ...
+-- Is candidate by default. Although it does not matter, until Raft is
+-- turned on.
+assert(box.cfg.raft_is_candidate)
+ | ---
+ | - true
+ | ...
+-- Ensure raft options are validated.
+box.cfg{raft_is_enabled = 100}
+ | ---
+ | - error: 'Incorrect value for option ''raft_is_enabled'': should be of type boolean'
+ | ...
+box.cfg{raft_is_candidate = 100}
+ | ---
+ | - error: 'Incorrect value for option ''raft_is_candidate'': should be of type boolean'
+ | ...
+box.cfg{raft_election_timeout = -1}
+ | ---
+ | - error: 'Incorrect value for option ''raft_election_timeout'': the value must be
+ |     a positive number'
+ | ...
+box.cfg{raft_election_timeout = 0}
+ | ---
+ | - error: 'Incorrect value for option ''raft_election_timeout'': the value must be
+ |     a positive number'
+ | ...
+
+-- When Raft is disabled, the instance is a follower. Does not
+-- try to become a leader, and does not block write operations.
+term = box.info.raft.term
+ | ---
+ | ...
+assert(box.info.raft.vote == 0)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.leader == 0)
+ | ---
+ | - true
+ | ...
+assert(not box.info.ro)
+ | ---
+ | - true
+ | ...
+
+-- Turned on Raft blocks writes until the instance becomes a
+-- leader.
+box.cfg{raft_is_candidate = false}
+ | ---
+ | ...
+box.cfg{raft_is_enabled = true}
+ | ---
+ | ...
+assert(box.info.raft.state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(box.info.ro)
+ | ---
+ | - true
+ | ...
+-- Term is not changed, because the instance can't be a candidate,
+-- and therefore didn't try to vote nor to bump the term.
+assert(box.info.raft.term == term)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.vote == 0)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.leader == 0)
+ | ---
+ | - true
+ | ...
+
+-- Candidate instance votes immediately, if sees no leader.
+box.cfg{raft_election_timeout = 1000}
+ | ---
+ | ...
+box.cfg{raft_is_candidate = true}
+ | ---
+ | ...
+test_run:wait_cond(function() return box.info.raft.state == 'leader' end)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.term > term)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.vote == box.info.id)
+ | ---
+ | - true
+ | ...
+assert(box.info.raft.leader == box.info.id)
+ | ---
+ | - true
+ | ...
+
+box.cfg{                                                                        \
+    raft_is_enabled = false,                                                    \
+    raft_is_candidate = true,                                                   \
+    raft_election_timeout = old_raft_election_timeout                           \
+}
+ | ---
+ | ...
+
+--
+-- See if bootstrap with Raft enabled works.
+--
+SERVERS = {'raft_replica1', 'raft_replica2', 'raft_replica3'}
+ | ---
+ | ...
+test_run:create_cluster(SERVERS, "replication")
+ | ---
+ | ...
+test_run:wait_fullmesh(SERVERS)
+ | ---
+ | ...
+is_leader_cmd = 'return box.info.raft.state == \'leader\''
+ | ---
+ | ...
+is_r1_leader = test_run:eval('raft_replica1', is_leader_cmd)[1]
+ | ---
+ | ...
+is_r2_leader = test_run:eval('raft_replica2', is_leader_cmd)[1]
+ | ---
+ | ...
+is_r3_leader = test_run:eval('raft_replica3', is_leader_cmd)[1]
+ | ---
+ | ...
+leader_count = is_r1_leader and 1 or 0
+ | ---
+ | ...
+leader_count = leader_count + (is_r2_leader and 1 or 0)
+ | ---
+ | ...
+leader_count = leader_count + (is_r3_leader and 1 or 0)
+ | ---
+ | ...
+assert(leader_count == 1)
+ | ---
+ | - true
+ | ...
+test_run:drop_cluster(SERVERS)
+ | ---
+ | ...
diff --git a/test/replication/raft_basic.test.lua b/test/replication/raft_basic.test.lua
new file mode 100644
index 000000000..faf3ad107
--- /dev/null
+++ b/test/replication/raft_basic.test.lua
@@ -0,0 +1,67 @@
+test_run = require('test_run').new()
+--
+-- gh-1146: Raft protocol for automated leader election.
+--
+
+old_raft_election_timeout = box.cfg.raft_election_timeout
+
+-- Raft is turned off by default.
+assert(not box.cfg.raft_is_enabled)
+-- Is candidate by default. Although it does not matter, until Raft is
+-- turned on.
+assert(box.cfg.raft_is_candidate)
+-- Ensure raft options are validated.
+box.cfg{raft_is_enabled = 100}
+box.cfg{raft_is_candidate = 100}
+box.cfg{raft_election_timeout = -1}
+box.cfg{raft_election_timeout = 0}
+
+-- When Raft is disabled, the instance is a follower. Does not
+-- try to become a leader, and does not block write operations.
+term = box.info.raft.term
+assert(box.info.raft.vote == 0)
+assert(box.info.raft.state == 'follower')
+assert(box.info.raft.leader == 0)
+assert(not box.info.ro)
+
+-- Turned on Raft blocks writes until the instance becomes a
+-- leader.
+box.cfg{raft_is_candidate = false}
+box.cfg{raft_is_enabled = true}
+assert(box.info.raft.state == 'follower')
+assert(box.info.ro)
+-- Term is not changed, because the instance can't be a candidate,
+-- and therefore didn't try to vote nor to bump the term.
+assert(box.info.raft.term == term)
+assert(box.info.raft.vote == 0)
+assert(box.info.raft.leader == 0)
+
+-- Candidate instance votes immediately, if sees no leader.
+box.cfg{raft_election_timeout = 1000}
+box.cfg{raft_is_candidate = true}
+test_run:wait_cond(function() return box.info.raft.state == 'leader' end)
+assert(box.info.raft.term > term)
+assert(box.info.raft.vote == box.info.id)
+assert(box.info.raft.leader == box.info.id)
+
+box.cfg{                                                                        \
+    raft_is_enabled = false,                                                    \
+    raft_is_candidate = true,                                                   \
+    raft_election_timeout = old_raft_election_timeout                           \
+}
+
+--
+-- See if bootstrap with Raft enabled works.
+--
+SERVERS = {'raft_replica1', 'raft_replica2', 'raft_replica3'}
+test_run:create_cluster(SERVERS, "replication")
+test_run:wait_fullmesh(SERVERS)
+is_leader_cmd = 'return box.info.raft.state == \'leader\''
+is_r1_leader = test_run:eval('raft_replica1', is_leader_cmd)[1]
+is_r2_leader = test_run:eval('raft_replica2', is_leader_cmd)[1]
+is_r3_leader = test_run:eval('raft_replica3', is_leader_cmd)[1]
+leader_count = is_r1_leader and 1 or 0
+leader_count = leader_count + (is_r2_leader and 1 or 0)
+leader_count = leader_count + (is_r3_leader and 1 or 0)
+assert(leader_count == 1)
+test_run:drop_cluster(SERVERS)
diff --git a/test/replication/raft_replica.lua b/test/replication/raft_replica.lua
new file mode 100644
index 000000000..8b4c740d8
--- /dev/null
+++ b/test/replication/raft_replica.lua
@@ -0,0 +1,30 @@
+#!/usr/bin/env tarantool
+
+local INSTANCE_ID = string.match(arg[0], "%d")
+local SOCKET_DIR = require('fio').cwd()
+
+local function instance_uri(instance_id)
+    return SOCKET_DIR..'/autobootstrap'..instance_id..'.sock';
+end
+
+require('console').listen(os.getenv('ADMIN'))
+
+box.cfg({
+    listen = instance_uri(INSTANCE_ID),
+    replication = {
+        instance_uri(1),
+        instance_uri(2),
+        instance_uri(3),
+    },
+    replication_timeout = 0.1,
+    raft_is_enabled = true,
+    raft_is_candidate = true,
+    raft_election_timeout = 0.1,
+    replication_synchro_quorum = 3,
+    -- To reveal more Raft logs.
+    log_level = 6,
+})
+
+box.once("bootstrap", function()
+    box.schema.user.grant('guest', 'super')
+end)
diff --git a/test/replication/raft_replica1.lua b/test/replication/raft_replica1.lua
new file mode 120000
index 000000000..d1f4d6f25
--- /dev/null
+++ b/test/replication/raft_replica1.lua
@@ -0,0 +1 @@
+raft_replica.lua
\ No newline at end of file
diff --git a/test/replication/raft_replica2.lua b/test/replication/raft_replica2.lua
new file mode 120000
index 000000000..d1f4d6f25
--- /dev/null
+++ b/test/replication/raft_replica2.lua
@@ -0,0 +1 @@
+raft_replica.lua
\ No newline at end of file
diff --git a/test/replication/raft_replica3.lua b/test/replication/raft_replica3.lua
new file mode 120000
index 000000000..d1f4d6f25
--- /dev/null
+++ b/test/replication/raft_replica3.lua
@@ -0,0 +1 @@
+raft_replica.lua
\ No newline at end of file

  parent reply	other threads:[~2020-09-19 15:58 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-09 23:16 [Tarantool-patches] [PATCH v2 00/11] dRaft Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 01/11] applier: store instance_id in struct applier Vladislav Shpilevoy
2020-09-14  9:38   ` Serge Petrenko
2020-09-19 15:44   ` Vladislav Shpilevoy
2020-09-21  6:23     ` Serge Petrenko
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 10/11] raft: introduce box.info.raft Vladislav Shpilevoy
2020-09-14  9:42   ` Serge Petrenko
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 11/11] [tosquash] raft: a swarm of minor fixes Vladislav Shpilevoy
2020-09-14 10:13   ` Serge Petrenko
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 02/11] box: introduce summary RO flag Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 03/11] wal: don't touch box.cfg.wal_dir more than once Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 04/11] replication: track registered replica count Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 05/11] [wip] box: do not register outgoing connections Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 06/11] raft: introduce persistent raft state Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 07/11] raft: introduce box.cfg.raft_* options Vladislav Shpilevoy
2020-09-09 23:16 ` [Tarantool-patches] [PATCH v2 08/11] raft: relay status updates to followers Vladislav Shpilevoy
2020-09-20 17:17   ` Vladislav Shpilevoy
2020-09-21  7:13     ` Serge Petrenko
2020-09-21 10:50   ` Serge Petrenko
2020-09-21 22:47     ` Vladislav Shpilevoy
2020-09-22  8:48       ` Serge Petrenko
2020-09-21 22:47   ` Vladislav Shpilevoy
2020-09-22  8:47     ` Serge Petrenko
2020-09-09 23:17 ` [Tarantool-patches] [PATCH v2 09/11] raft: introduce state machine Vladislav Shpilevoy
2020-09-19 15:49   ` Vladislav Shpilevoy
2020-09-19 15:50     ` Vladislav Shpilevoy
2020-09-21  8:20       ` Serge Petrenko
2020-09-21  8:22     ` Serge Petrenko
2020-09-21  8:34       ` Serge Petrenko
2020-09-21 22:47     ` Vladislav Shpilevoy
2020-09-22  8:49       ` Serge Petrenko
2020-09-22 22:48   ` Vladislav Shpilevoy
2020-09-23  9:59     ` Serge Petrenko
2020-09-23 20:31       ` Vladislav Shpilevoy
2020-09-24  9:34         ` Serge Petrenko
2020-09-19 15:58 ` Vladislav Shpilevoy [this message]
2020-09-19 15:59   ` [Tarantool-patches] [PATCH v2 12/11] dRaft Vladislav Shpilevoy
2020-09-21  7:24     ` Serge Petrenko
2020-09-21 22:48   ` [Tarantool-patches] [PATCH v2 12/11] raft: add tests Vladislav Shpilevoy
2020-09-30 10:56 ` [Tarantool-patches] [PATCH v2 00/11] dRaft Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5a7cf2f2-1b7c-28be-688f-d604a64d0623@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=gorcunov@gmail.com \
    --cc=sergepetrenko@tarantool.org \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches]  [PATCH v2 12/11] dRaft' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox