diff --git a/test/int/conftest.py b/test/int/conftest.py index e32418377e9e484d9eac9e3f2c79b9e71a8cbbd4..cbdbcc2a76b348cf2bbcb9aadf1e1d9dcc18de2e 100644 --- a/test/int/conftest.py +++ b/test/int/conftest.py @@ -300,7 +300,7 @@ class Instance: assert want == have - @funcy.retry(tries=20, timeout=0.1) + @funcy.retry(tries=30, timeout=0.2) def wait_ready(self): status = self._raft_status() assert status.is_ready diff --git a/test/int/test_couple.py b/test/int/test_couple.py index 69685dc23a43cafd2353875320c18976ceb54df9..eefaac11360b20c56e51ce1b48c55e97888213dd 100644 --- a/test/int/test_couple.py +++ b/test/int/test_couple.py @@ -50,3 +50,56 @@ def test_failover(cluster2: Cluster): i2.assert_raft_status("Leader") retry_call(do_test) + + +def test_restart_follower(cluster2: Cluster): + # Given a cluster of two instances - i1 (leader) and i2 (follower) + # When i2 restarts + # Then it's able to start and remain a follower + + i1, i2 = cluster2.instances + i2.restart() + i2.wait_ready() + i1.assert_raft_status("Leader") + i2.assert_raft_status("Follower") + + +def test_restart_leader(cluster2: Cluster): + # Given a cluster of two instances - i1 (leader) and i2 (follower) + # When i1 restarts + # Then it's able to start and make a proposal. + # No assuptions about leadership are made though. + + i1, _ = cluster2.instances + i1.restart() + i1.wait_ready() + assert i1.raft_propose_eval("return") + + +@pytest.mark.xfail # FIXME +def test_restart_both(cluster2: Cluster): + # Given a cluster of 2 instances - i1, i2 + # When both instances are stopped and then started again + # Then both can become ready and handle proposals. + + i1, i2 = cluster2.instances + i1.terminate() + i2.terminate() + + @funcy.retry(tries=20, timeout=0.1) + def wait_alive(instance): + assert instance._raft_status().is_ready is False + + i1.start() + # This synchronization makes sure the test fails. + # i1 has already initialized raft node but can't win election yet + # i2 starts discovery and fails: leader_id is unknown for node 1 + wait_alive(i1) + i2.start() + + i1.wait_ready() + i2.wait_ready() + + i1.raft_propose_eval("rawset(_G, 'check', true)") + assert i1.eval("return check") is True + assert i2.eval("return check") is True