Skip to content

Commit

Permalink
Merge pull request #991 from Joncom/on-recovery
Browse files Browse the repository at this point in the history
Test if gun.on() callback fires after relay peer crashes
  • Loading branch information
amark authored Jul 24, 2020
2 parents 97aa976 + 2ddb526 commit bd417b9
Showing 1 changed file with 224 additions and 0 deletions.
224 changes: 224 additions & 0 deletions test/panic/on-recovery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// Gun is supposed to be able to gracefully handle peers going offline and then
// coming back online. If a client has subscribed to some piece of data via the
// gun.on() API method, the subscription should continue to work if a peer goes
// offline briefly and then comes back online. This test confirms that such is
// the case, or fails otherwise.

// Important: It turns out that it's very important that both browsers tabs be
// visible/active throughout the tests, because an inactive tab will NOT
// reconnect to the relay peer until the tab is active again. (Chrome 83)

var config = {
IP: require('ip').address(),
port: 8765,
servers: 2,
browsers: 2,
route: {
'/': __dirname + '/index.html',
'/gun.js': __dirname + '/../../gun.js',
'/jquery.js': __dirname + '/../../examples/jquery.js'
}
}

var panic = require('panic-server');
panic.server().on('request', function(req, res){
config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
}).listen(config.port);

var clients = panic.clients;
var manager = require('panic-manager')();

manager.start({
clients: Array(config.servers).fill().map(function(u, i){
return {
type: 'node',
port: config.port + (i + 1)
}
}),
panic: 'http://' + config.IP + ':' + config.port
});

var servers = clients.filter('Node.js');
var bob = servers.pluck(1);
var carl = servers.excluding(bob).pluck(1);
var browsers = clients.excluding(servers);
var alice = browsers.pluck(1);
var dave = browsers.excluding(alice).pluck(1);

describe("gun.on should receive updates after crashed relay peer comes back online", function(){
this.timeout(10 * 60 * 1000);

it("Servers have joined!", function(){
return servers.atLeast(config.servers);
});

it("GUN started!", function(){
return bob.run(function(test){
var env = test.props;
var filepath = env.dir + '/data';
test.async();
var fs = require('fs');
try { if (fs.existsSync(filepath)) { fs.rmdirSync(filepath, { recursive: true }); } } catch (e) { console.error(e); test.fail(''); }
var server = require('http').createServer(function(req, res){
res.end("I AM BOB");
});
var port = env.config.port + 1;
try { var Gun = require(env.dir + '/../../index.js'); } catch(e) { console.error(e); test.fail(''); }
var gun = Gun({file: filepath, web: server});
server.listen(port, function(){
test.done();
});
}, {config: config, dir: __dirname});
});

it(config.browsers +" browser(s) have joined!", function(){
console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
return browsers.atLeast(config.browsers);
});

it("Browsers initialized gun!", function(){
var tests = [], i = 0;
browsers.each(function(client, id){
tests.push(client.run(function(test){
try{ localStorage.clear() }catch(e){}
try{ indexedDB.deleteDatabase('radata') }catch(e){}
var env = test.props;
var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
window.ref = gun.get('a');
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});

it("Dave subscribed to updates using gun.on()", function(){
return dave.run(function(test){
console.log("I AM DAVE");
test.async();
ref.on(function(data){
console.log("Just received data: ", data);
if(data.hello === 'world') { window.receivedFirst = true; }
if(data.foo === 'bar') { window.receivedSecond = true; }
});
test.done();
});
});

it("Alice put first data", function(){
return alice.run(function(test){
console.log("I AM ALICE");
test.async();
ref.put({hello: 'world'}, function(ack){
if(!ack.err) {
test.done();
}
});
});
});

it("Dave received first data", function(){
return dave.run(function(test){
test.async();
var myInterval;
myInterval = setInterval(function() {
if(window.receivedFirst) {
clearInterval(myInterval);
test.done();
}
}, 10);
});
});

it("Killed relay peer", function(){
return bob.run(function(test){
test.async();
process.exit();
});
});

it("Waited 1 second", function(done){
setTimeout(done, 1000);
});

it("Alice put second data", function(){
return alice.run(function(test){
test.async();
ref.put({foo: 'bar'}, function(ack){
if(!ack.err) {
test.done();
}
});
});
});

// FIXME: Don't copy paste the entire block!!
it("Restored relay peer", function(){
return carl.run(function(test){
var env = test.props;
var filepath = env.dir + '/data';
test.async();
var fs = require('fs');
try { if (fs.existsSync(filepath)) { fs.rmdirSync(filepath, { recursive: true }); } } catch (e) { console.error(e); test.fail(''); }
var server = require('http').createServer(function(req, res){
res.end("I AM CARL");
});
var port = env.config.port + 1;
try { var Gun = require(env.dir + '/../../index.js'); } catch(e) { console.error(e); test.fail(''); }
var gun = Gun({file: filepath, web: server});
server.listen(port, function(){
test.done();
});
}, {config: config, dir: __dirname});
});

it("Browsers reconnected", function() {
var tests = [], i = 0;
browsers.each(function(client, id){
tests.push(client.run(function(test){
test.async();
var config = test.props.config;
var seconds = 15;
var timeout = Date.now() + seconds * 1000;
var url = "http://"+ config.IP +":"+ (config.port+1) +"/gun";
var peers = ref.back(1)._.opt.peers;
var i;
i = setInterval(function() {
if(peers[url] && peers[url].wire.readyState === 1) {
clearInterval(i);
test.done();
return;
}
if(Date.now() >= timeout) {
test.fail('Timed out after ' + seconds + ' seconds');
return;
}
}, 10);
}, {config: config}));
});
return Promise.all(tests);
});

it("Dave received second data", function(){
return dave.run(function(test){
test.async();
var seconds = 60;
var timeout = Date.now() + seconds * 1000;
var i;
i = setInterval(function() {
if(window.receivedSecond) {
test.done();
return;
}
if(Date.now() >= timeout) {
test.fail('Timed out after ' + seconds + ' seconds');
return;
}
}, 10);
});
});

after("Everything shut down.", function(){
return bob.run(function(){
process.exit();
});
});
});

0 comments on commit bd417b9

Please sign in to comment.