Skip to content

Instantly share code, notes, and snippets.

@PsychoLlama
Created June 1, 2016 18:18
Show Gist options
  • Save PsychoLlama/7f8341e44b40a0d6cc9f3e5eeb1c6e71 to your computer and use it in GitHub Desktop.
Save PsychoLlama/7f8341e44b40a0d6cc9f3e5eeb1c6e71 to your computer and use it in GitHub Desktop.
GunDB catastrophic fault-tolerance test case
{
"dependencies": {
"mocha": "^2.5.3",
"panic-server": "^0.3.0",
"selenium-webdriver": "^2.53.2"
}
}
var panic = require('panic-client');
var ports = require('./ports');
var Gun = require('gun');
var gun = new Gun({
file: 'delete-me.json'
});
var http = require('http');
var server = new http.Server(gun.wsp.server);
gun.wsp(server);
server.listen(ports.gun);
panic.server('http://localhost:' + ports.panic);
/*
This file should be one
folder deeper than every
other file. It requires
mocha to run.
*/
var panic = require('panic-server');
var spawn = require('child_process').spawn;
var path = require('path');
var http = require('http');
var fs = require('fs');
var ports = require('../ports');
var wd = require('selenium-webdriver');
function open(url) {
var driver = new wd.Builder()
.forBrowser('phantomjs')
.build();
driver.get(url);
return driver;
}
open('http://localhost:' + ports.panic + '/index.html');
open('http://localhost:' + ports.panic + '/index.html');
var staticServer = new http.Server(function (req, res) {
if (req.url === '/') {
req.url = '/index.html';
}
var file = path.join(__dirname, '..', req.url);
try {
var page = fs.readFileSync(file, 'utf8');
res.end(page);
} catch (e) {
// don't care
}
});
var server = panic.clients.filter('Node.js').pluck(1);
var browsers = panic.clients.excluding(server);
var alice = browsers.pluck(1);
var bob = browsers.excluding(alice).pluck(1);
var serverPath = path.join(__dirname, '..', 'gun-server.js');
// start the server on :8080
spawn('node', [serverPath]);
function waitFor (num, list) {
return new Promise(function (res) {
function ready() {
if (list.length < num) {
return;
}
res();
list.removeListener('add', ready);
return true;
}
if (!ready()) {
list.on('add', ready);
}
});
}
before(function () {
this.timeout(1500000);
// start the panic server
panic.server(staticServer).listen(ports.panic);
return waitFor(2, browsers)
.then(function () {
return waitFor(1, server);
});
});
var scope = {
uniqueKey: Math.random().toString(16).slice(2),
file: path.join(process.cwd(), 'delete-me.json'),
gunFile: path.join(__dirname, '..', 'gun.js'),
'@scope': true
}
describe('The holy grail', function () {
it('should allow full recovery', function () {
this.timeout(1500000);
return browsers.run(function () {
localStorage.clear();
})
.then(function () {
return browsers.run(function () {
window.ref = gun.get(uniqueKey).put({
text: 'ignore'
});
}, scope)
})
.then(function () {
return alice.run(function (done) {
// alice saves some data
ref.path('text').put('Initial text', done);
});
})
.then(function () {
return bob.run(function (done) {
var ctx = this;
ref.path('text').on(function (data) {
if (data === 'ignore') {
return;
}
// bob sees alice's data
if (data !== 'Initial text') {
ctx.fail('Wrong data showed up: ' + JSON.stringify(data));
}
done();
});
});
})
.then(function () {
return server.run(function () {
var fs = require('fs');
// destroy the data
fs.unlinkSync(file);
// crash the server
process.exit(0);
}, scope);
})
.then(function () {
return alice.run(function (done) {
ref.path('text').put('A conflicting update');
setTimeout(done, 50);
});
})
.then(function () {
return bob.run(function () {
ref.path('text').put('B conflicting update');
});
})
.then(function () {
spawn('node', [serverPath]);
return waitFor(1, server);
})
.then(function () {
return browsers.run(function (done) {
var ctx = this;
ref.path('text').on(function (value) {
if (value === 'B conflicting update') {
done();
}
});
});
});
});
});
after(function () {
if (server.length) {
return server.run(function () {
process.exit(0);
});
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Holy grail demo</title>
</head>
<body>
<script src='panic.js'></script>
<script src='http://localhost:8080/gun.js'></script>
<script>
(function () {
var req = new XMLHttpRequest();
req.overrideMimeType('application/json');
req.open('GET', 'ports.json');
req.addEventListener('load', function () {
var ports = JSON.parse(req.responseText);
var server = 'http://localhost:' + ports.gun + '/gun';
window.gun = new Gun(server);
panic.server('http://localhost:' + ports.panic);
});
req.send();
}());
</script>
</body>
</html>
{
"panic": 3000,
"gun": 8080
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment