From 1d8dfc861c1f1be9585cc380e6f93a251db6b28e Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Fri, 29 Sep 2023 00:35:37 +0300 Subject: [PATCH] Add a test for leadership expiration --- tinyraft.spec.js | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/tinyraft.spec.js b/tinyraft.spec.js index 8971e84..9da77bf 100644 --- a/tinyraft.spec.js +++ b/tinyraft.spec.js @@ -1,9 +1,9 @@ const TinyRaft = require('./tinyraft.js'); -function newNode(id, nodes, partitions) +function newNode(id, nodes, partitions, mod) { partitions = partitions || {}; - let n = new TinyRaft({ + let cfg = { nodes: [ 1, 2, 3, 4, 5 ], nodeId: id, heartbeatTimeout: 100, @@ -16,7 +16,10 @@ function newNode(id, nodes, partitions) setImmediate(function() { nodes[to].onReceive(n.nodeId, msg); }); } }, - }); + }; + if (mod) + mod(cfg); + let n = new TinyRaft(cfg); n.on('change', (st) => { console.log( @@ -27,13 +30,13 @@ function newNode(id, nodes, partitions) nodes[id] = n; } -function newNodes(count, partitions) +function newNodes(count, partitions, mod) { partitions = partitions || {}; const nodes = {}; for (let i = 1; i <= count; i++) { - newNode(i, nodes, partitions); + newNode(i, nodes, partitions, mod); } for (let i = 1; i <= count; i++) { @@ -148,10 +151,40 @@ async function testAddNode() console.log('testAddNode: OK'); } +async function testLeadershipExpiration() +{ + const partitions = {}; + const nodes = newNodes(5, partitions, cfg => cfg.leadershipTimeout = 1500); + // Check that 5 nodes are in quorum after 2000ms + await new Promise(ok => setTimeout(ok, 2000)); + checkQuorum(nodes, 5); + // Break network on the leader + let leader = nodes[1].leader; + console.log("stopping the leader's ("+leader+") network"); + for (let i = 1; i <= 5; i++) + { + partitions[i+'-'+leader] = true; + partitions[leader+'-'+i] = true; + } + // Check that the leader loses leadership after 2 * leadershipTimeout + await new Promise(ok => setTimeout(ok, 3000)); + if (nodes[leader].state != TinyRaft.CANDIDATE) + { + throw new Error("leadership expiration doesn't work"); + } + // Clean up + for (const id in nodes) + { + nodes[id].stop(); + } + console.log('testLeadershipExpiration: OK'); +} + async function run() { await testStartThenRemoveNode(); await testAddNode(); + await testLeadershipExpiration(); process.exit(0); }