diff --git a/README.md b/README.md
index 046eb01..0e37f67 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,6 @@
Try it out !
```bash
- docker image build -t ring-election .
docker-compose up
```
Check assigned partitions to local:9000/status or change the port to 9001/9002
@@ -138,7 +137,14 @@ Tag 1.0 and public on npm
How to contribute
Take tasks from todo list, develop a new feature or fix a bug and do a pull request.
How to run tests
-npm run test
+Unit tests
+npm run test
+Integration tests
+cd test/integration
+./integration.sh
+npm run integration-test
+
+
Versioning
We use (http://semver.org/) for versioning.
diff --git a/package.json b/package.json
index 14f4503..a24d0a3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ring-election",
- "version": "0.0.16",
+ "version": "1.0.0",
"description": "Leader and followers algorithm to make partitioning easy.",
"main": "index.js",
"engines": {
diff --git a/test/hearthbeat.test.js b/test/hearthbeat.test.js
index 2f23f9f..5564650 100644
--- a/test/hearthbeat.test.js
+++ b/test/hearthbeat.test.js
@@ -18,7 +18,7 @@ describe('Hearth beat', () => {
setTimeout(() => {
expect(count >= 10).toBeTruthy();
done();
- }, 20);
+ }, 200);
});
it('Should do an hearth check with correct frequency', done => {
@@ -33,6 +33,6 @@ describe('Hearth beat', () => {
setTimeout(() => {
expect(count).toBe(0);
done();
- }, 20);
+ }, 200);
});
});
diff --git a/test/integration/integration.js b/test/integration/integration.js
index e98b2bc..75be6ba 100644
--- a/test/integration/integration.js
+++ b/test/integration/integration.js
@@ -4,64 +4,102 @@ const expect = require('expect');
const request = require('request');
var exec = require('child_process').exec;
-let shouldStartWell = (err, response, body , done , nodeNumber) => {
- expect(response.statusCode).toBe(200);
- expect(body).toBeDefined();
- let resp = JSON.parse(body);
- expect(resp.length).toBe(3);
- // actually the leader has not assigned to any partition.
- let leader = resp.find(node => node.partitions.length == 0);
- expect(leader).toBeDefined();
- // expect other two nodes to have 5 partitions assigned per each.
- resp
- .filter(node => node.partitions.length > 0)
- .forEach(n => {
- expect(n.partitions.length).toBe(5);
- });
- if(nodeNumber == 3)
- done();
- };
+let basicCheck =(response, body,expectedPartitions,expectedNodes) => {
+ expect(response.statusCode).toBe(200);
+ expect(body).toBeDefined();
+ let resp = JSON.parse(body);
+ expect(resp.length).toBe(expectedNodes);
+ // actually the leader has not assigned to any partition.
+ let leader = resp.find(node => node.partitions.length == 0);
+ expect(leader).toBeDefined();
+ // expect other node to have 10 partitions assigned per each.
+ resp
+ .filter(node => node.partitions.length > 0)
+ .forEach(n => {
+ expect(n.partitions.length).toBe(expectedPartitions);
+ });
+};
-describe('Integration test', () => {
+let shouldStartWell = (err, response, body, done, nodeNumber) => {
+ basicCheck(response, body,5 , 3);
+ if (nodeNumber == 3) done();
+};
+
+let shouldReassignPartitions = (err, response, body, done, nodeNumber) => {
+ basicCheck(response, body , 10 , 2);
+ // restart container
+ if (nodeNumber == 2) {
+ exec('docker container restart ring-election_node-2_1', error => {
+ expect(error).toBeFalsy();
+ if (!error) done();
+ });
+ }
+};
+
+let shouldHandleLeaderFailure = (err, response, body, done, nodeNumber) => {
+ basicCheck(response, body , 10 , 2);
+ // restart container
+ if (nodeNumber == 2) {
+ exec('docker container restart ring-election_node-0_1', error => {
+ expect(error).toBeFalsy();
+ if (!error) done();
+ });
+ }
+};
+
+describe('Integration test', () => {
it('Should start well', done => {
- request('http://localhost:9000/status', (err,resp,body) => {
- shouldStartWell(err,resp,body,done,1);
+ request('http://localhost:9000/status', (err, resp, body) => {
+ shouldStartWell(err, resp, body, done, 1);
});
- request('http://localhost:9001/status', (err,resp,body) => {
- shouldStartWell(err,resp,body,done,2);
+ request('http://localhost:9001/status', (err, resp, body) => {
+ shouldStartWell(err, resp, body, done, 2);
});
- request('http://localhost:9002/status', (err,resp,body) => {
- shouldStartWell(err,resp,body,done,3);
+ request('http://localhost:9002/status', (err, resp, body) => {
+ shouldStartWell(err, resp, body, done, 3);
});
});
-
-
it('Should reassign partitions when a node is down', done => {
-
exec('docker container stop ring-election_node-2_1', err => {
expect(err).toBeFalsy();
setTimeout(() => {
- request('http://localhost:9000/status', (err, response, body) => {
- expect(response.statusCode).toBe(200);
- expect(body).toBeDefined();
- let resp = JSON.parse(body);
- expect(resp.length).toBe(2);
- // actually the leader has not assigned to any partition.
- let leader = resp.find((node) => node.partitions.length == 0);
- expect(leader).toBeDefined();
- // expect other node to have 5 partitions assigned per each.
- resp.filter(node => node.partitions.length > 0).forEach(n => {
- expect(n.partitions.length).toBe(10);
- });
- exec('docker container restart ring-election_node-2_1', err => {
- if(!err)
- done();
- else
- console.error(err);
- });
+ request('http://localhost:9000/status', (error, resp, body) => {
+ shouldReassignPartitions(error, resp, body, done, 1);
+ });
+ request('http://localhost:9001/status', (error, resp, body) => {
+ shouldReassignPartitions(error, resp, body, done, 2);
+ });
+ }, 15000);
+ });
+ });
+
+ it('Another node should become leader if the leader fail', done => {
+ // assume that the node-0 is the leader, it should always be the leader
+ exec('docker container stop ring-election_node-0_1', err => {
+ expect(err).toBeFalsy();
+ setTimeout(() => {
+ // another node must become the leader.
+ request('http://localhost:9001/status', (error, resp, body) => {
+ shouldHandleLeaderFailure(error, resp, body, done, 1);
+ });
+ request('http://localhost:9002/status', (error, resp, body) => {
+ shouldHandleLeaderFailure(error, resp, body, done, 2);
});
+ // when leader is added again , it should be a follower
+ setTimeout(() => {
+ request('http://localhost:9000/status', (error, resp, body) => {
+ shouldReassignPartitions(error, resp, body, done);
+ });
+ request('http://localhost:9001/status', (error, resp, body) => {
+ shouldReassignPartitions(error, resp, body, done);
+ });
+ request('http://localhost:9002/status', (error, resp, body) => {
+ shouldReassignPartitions(error, resp, body, done);
+ done();
+ });
+ }, 10000);
}, 15000);
});
});