-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #991 from Joncom/on-recovery
Test if gun.on() callback fires after relay peer crashes
- Loading branch information
Showing
1 changed file
with
224 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); | ||
}); |