load testing!

This commit is contained in:
Mark Nadal 2017-03-11 07:03:55 -08:00
parent a700afba73
commit ec3288e583
13 changed files with 760 additions and 535 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ node_modules
npm-debug.log npm-debug.log
yarn.lock yarn.lock
*data.json *data.json
*data*
*.db *.db
.idea/ .idea/
*.bak *.bak

View File

@ -1,8 +1,21 @@
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8080; var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8080;
var Gun = require('../'); var Gun = require('../');
var server = require('http').createServer(function(req, res){
if(Gun.serve(req, res)){ return } // filters gun requests!
require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files!
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(require('fs')
.readFileSync(require('path')
.join(__dirname, 'index.html') // or default to index
));
}).pipe(res); // stream
});
var gun = Gun({ var gun = Gun({
file: 'data.json', file: 'data.json',
web: server,
s3: { s3: {
key: '', // AWS Access Key key: '', // AWS Access Key
secret: '', // AWS Secret Token secret: '', // AWS Secret Token
@ -10,16 +23,6 @@ var gun = Gun({
} }
}); });
var server = require('http').createServer(function(req, res){
if(gun.wsp.server(req, res)){
return; // filters gun requests!
}
require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files!
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(require('fs').readFileSync(require('path').join(__dirname, 'index.html'))); // or default to index
}).pipe(res); // stream
});
gun.wsp(server);
server.listen(port); server.listen(port);
console.log('Server started on port ' + port + ' with /gun'); console.log('Server started on port ' + port + ' with /gun');

852
gun.js

File diff suppressed because it is too large Load Diff

View File

@ -5,30 +5,54 @@
var Gun = require('../gun'), var Gun = require('../gun'),
fs = require('fs'); fs = require('fs');
var files = {};
Gun.on('put', function(at){ Gun.on('put', function(at){
//console.log("file write", Gun.obj.copy(at), at.gun.back(-1)._.opt.file);
this.to.next(at); this.to.next(at);
var fileOpt = at.gun.back('opt._file')
if(!fileOpt.use){ return } var root = at.gun.back(-1);
var f = at.gun.back('opt._file')
if(!f.use){ return }
var graph = at.put, opt = at.opt || {}; var graph = at.put, opt = at.opt || {};
var Graph = fileOpt.gun._.graph var Graph = f.gun._.graph
Gun.obj.map(graph, function(node, soul){ Gun.obj.map(graph, function(node, soul){
fileOpt.disk.graph[soul] = Graph[soul] || graph[soul]; f.disk.graph[soul] = Graph[soul] || graph[soul];
}); });
graph = JSON.stringify(fileOpt.disk, null, 2); f.count = (f.count || 0) + 1;
// TODO: Allow for a `fs.writeFile` compatible module, that is more reliable/safe, to be passed in through the options. if(!at['@']){ // don't ack other acks!
fs.writeFile(opt.file || fileOpt.file, graph, function(err){ (f.check || (f.check = {}))[at['#']] = root;
fileOpt.gun.on('in', { }
'@': at['#'], function save(){
ok: err? undefined : 1, clearTimeout(f.wait);
err: err var ack = f.check;
f.count = 0;
f.wait = false;
f.check = {};
graph = JSON.stringify(f.disk, null, 2);
// TODO: Allow for a `fs.writeFile` compatible module, that is more reliable/safe, to be passed in through the options.
fs.writeFile(opt.file || f.file, graph, function(err){
Gun.obj.map(ack, function(root, id){
root.on('in', {
'@': id,
ok: err? undefined : 1,
err: err || undefined
});
});
}); });
}); }
if(f.count >= 10000){ // goal is to do 10K inserts/second.
return save();
}
if(f.wait){ return }
clearTimeout(f.wait);
f.wait = setTimeout(save, 1000);
}); });
Gun.on('get', function(at){ Gun.on('get', function(at){
var fileOpt = at.gun.back('opt._file');
//if(at.cap && fileOpt.use){ at.cap-- }
this.to.next(at); this.to.next(at);
var fileOpt = at.gun.back('opt._file')
if(!fileOpt.use){ return } if(!fileOpt.use){ return }
var opt = at.opt || {}; var opt = at.opt || {};
var soul = at.get['#']; var soul = at.get['#'];
@ -39,7 +63,8 @@ Gun.on('get', function(at){
} }
fileOpt.gun.on('in', { fileOpt.gun.on('in', {
put: Gun.graph.node(node), put: Gun.graph.node(node),
'@': at['#'] '@': at['#'],
how: 'file'
}) })
}); });
@ -75,7 +100,7 @@ Gun.on('opt', function(at){
opt._file.use = true; opt._file.use = true;
opt._file.file = String(opt.file || opt._file.file || 'data.json'); opt._file.file = String(opt.file || opt._file.file || 'data.json');
opt._file.raw = opt._file.raw || ((fs.existsSync || require('path').existsSync)(opt._file.file) ? fs.readFileSync(opt._file.file).toString() : null); opt._file.raw = opt._file.raw || ((fs.existsSync || require('path').existsSync)(opt._file.file) ? fs.readFileSync(opt._file.file).toString() : null);
opt._file.disk = opt._file.disk || Gun.obj.ify(opt._file.raw || {graph: {}}); opt._file.disk = files[opt._file.file] = files[opt._file.file] || opt._file.disk || Gun.obj.ify(opt._file.raw || {graph: {}});
opt._file.disk.graph = opt._file.disk.graph || {}; opt._file.disk.graph = opt._file.disk.graph || {};
opt._file.gun = gun; opt._file.gun = gun;
}); });

View File

@ -1,4 +1,7 @@
;(function(){ ;(function(){
if(!process.env.AWS_S3_BUCKET){ return }
var Gun = require('../gun'); var Gun = require('../gun');
var S3 = require('./aws'); var S3 = require('./aws');

11
lib/serve.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = function serve(req, res, next){
if(!req || !res){ return false }
next = next || serve;
if(!req.url){ return next() }
if(0 <= req.url.indexOf('gun.js')){
res.writeHead(200, {'Content-Type': 'text/javascript'});
res.end(serve.js = serve.js || require('fs').readFileSync(__dirname + '/../gun.js'));
return true;
}
return next();
}

View File

@ -1,7 +1,9 @@
;(function(){ ;(function(){
var Gun = require('../gun'); var Gun = require('../gun');
Gun.serve = require('./serve');
require('./s3'); require('./s3');
require('./wsp/server'); require('./uws');
//require('./wsp/server');
require('./file'); require('./file');
module.exports = Gun; module.exports = Gun;
}()); }());

View File

@ -4,25 +4,29 @@ var WebSocket = require('uws');
var url = require('url'); var url = require('url');
var con; console.log("Experimental high performance uWS server is being used.");
Gun.on('opt', function(at){ Gun.on('opt', function(at){
this.to.next(at); this.to.next(at);
if(at.once){ return } if(at.once){ return }
var opt = at.opt.uws || at.opt.ws || (at.opt.uws = {}); var opt = at.opt.uws || at.opt.ws || (at.opt.uws = {});
var cat = at.gun.back(-1)._; var cat = (at.gun.back(-1)._);
opt.server = new WebSocket.Server(opt || {port: 8080}); opt.server = opt.server || at.opt.web;
if(opt.server && opt.server.use){ // if ExpressJS
opt.server.use(Gun.serve);
}
opt.web = new WebSocket.Server(opt);
var peers = cat.opt.peers; var peers = cat.opt.peers;
console.log("????", opt.server); opt.web.on('connection', function(ws){
opt.server.on('connection', function(ws){
ws.upgradeReq = ws.upgradeReq || {}; ws.upgradeReq = ws.upgradeReq || {};
ws.url = url.parse(ws.upgradeReq.url||'', true); ws.url = url.parse(ws.upgradeReq.url||'', true);
ws.id = ws.id || Gun.text.random(6); ws.id = ws.id || Gun.text.random(6);
peers[ws.id] = {wire: ws}; peers[ws.id] = {wire: ws};
ws.on('message', function(msg){ ws.on('message', function(msg){
console.log("MESSAGE", msg); //console.log("MESSAGE", msg);
receive(msg, ws, cat); receive(msg, ws, cat);
}); });
ws.on('close', function(){ ws.on('close', function(){
@ -31,22 +35,47 @@ Gun.on('opt', function(at){
}); });
}); });
function receive(msg, wire, cat){
if(!cat){ return }
try{msg = JSON.parse(msg);
msg.url = wire.url;
}catch(e){}
cat.gun.on('in', msg.body || msg);
}
var message; var message;
Gun.on('out', function(at){ Gun.on('out', function(at){
this.to.next(at); this.to.next(at);
var cat = at.gun._.root._; var cat = at.gun._.root._;
message = JSON.stringify({body: at, headers: {}}); message = JSON.stringify(at);
if(cat.udrain){
cat.udrain.push(message);
return;
}
cat.udrain = [];
setTimeout(function(){
if(!cat.udrain){ return }
//if(count += cat.udrain.length){ console.log("msg out:", count) }
var tmp = cat.udrain;
cat.udrain = null;
message = JSON.stringify(tmp);
Gun.obj.map(cat.opt.peers, send, cat);
},1);
Gun.obj.map(cat.opt.peers, send, cat); Gun.obj.map(cat.opt.peers, send, cat);
}); });
var count = 0;
function receive(msg, wire, cat){
if(!cat){ return }
try{msg = JSON.parse(msg);
}catch(e){}
if(msg instanceof Array){
var i = 0, m; while(m = msg[i++]){
receive(m, wire, cat);
}
return;
}
//if(++count){ console.log("msg in:", count) }
//msg.url = wire.url;
cat.gun.on('in', msg.body || msg);
}
// EVERY message taken care of. The "extra" ones are from in-memory not having "asked" for it yet - which we won't want it to do for foreign requests. Likewise, lots of chattyness because the put/ack replies happen before the `get` syncs so everybody now has it in-memory already to reply with.
function send(peer){ function send(peer){
var msg = message, cat = this; var msg = message, cat = this;
var wire = peer.wire || open(peer, cat); var wire = peer.wire || open(peer, cat);
@ -66,6 +95,7 @@ function open(peer, as){
reconnect(peer, as); reconnect(peer, as);
}); });
wire.on('error', function(error){ wire.on('error', function(error){
if(!error){ return }
if(error.code === 'ECONNREFUSED'){ if(error.code === 'ECONNREFUSED'){
reconnect(peer, as); reconnect(peer, as);
} }

View File

@ -16,18 +16,26 @@ Gun.on('opt', function (at) {
gun.__ = at.root._; gun.__ = at.root._;
gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {}; gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {};
if(gun.__.opt.web){
setTimeout(function(){
if(gun.__.opt.web.use){
gun.__.opt.web.use(Gun.serve);
}
start(gun.__.opt.web);
},1);
}
function start (server, port, app) { function start (server, port, app) {
if (app && app.use) { if (app && app.use) {
app.use(gun.wsp.server); app.use(gun.wsp.server);
} }
server = gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || server; server = gun.__.opt.ws.server = gun.__.opt.ws.server || gun.__.opt.web || opt.ws.server || server;
if (!gun.wsp.ws) { if (!gun.wsp.ws) {
//console.log("????????", gun.__.opt.ws);
gun.wsp.ws = new WSS(gun.__.opt.ws); gun.wsp.ws = new WSS(gun.__.opt.ws);
attach(gun, gun.wsp.ws); attach(gun, gun.wsp.ws);
} }
gun.wsp.ws = gun.wsp.ws || new WSS(gun.__.opt.ws);
require('./ws')(gun.wsp.ws, function (req, res) { require('./ws')(gun.wsp.ws, function (req, res) {
var ws = this; var ws = this;
req.headers['gun-sid'] = ws.sid = ws.sid ? ws.sid : req.headers['gun-sid']; req.headers['gun-sid'] = ws.sid = ws.sid ? ws.sid : req.headers['gun-sid'];
@ -45,6 +53,7 @@ Gun.on('opt', function (at) {
gun.__.opt.ws.port = gun.__.opt.ws.port || opt.ws.port || port || 80; gun.__.opt.ws.port = gun.__.opt.ws.port || opt.ws.port || port || 80;
} }
var wsp = gun.wsp = gun.wsp || function (server) { var wsp = gun.wsp = gun.wsp || function (server) {
console.log("WARNING: gun.wsp(server) should be switched to Gun({web: server}) by v0.7!")
if (!server) { return gun; } if (!server) { return gun; }
if (Gun.fns.is(server.address)) { if (Gun.fns.is(server.address)) {
if (server.address()) { if (server.address()) {

View File

@ -1,6 +1,6 @@
{ {
"name": "gun", "name": "gun",
"version": "0.6.3", "version": "0.6.4",
"description": "Graph engine", "description": "Graph engine",
"main": "index.js", "main": "index.js",
"browser": "gun.min.js", "browser": "gun.min.js",
@ -50,7 +50,7 @@
"dependencies": { "dependencies": {
"aws-sdk": "~>2.15.0", "aws-sdk": "~>2.15.0",
"formidable": "~>1.0.15", "formidable": "~>1.0.15",
"ws": "~>1.0.1" "uws": "~>0.13.0"
}, },
"devDependencies": { "devDependencies": {
"express": "~>4.13.4", "express": "~>4.13.4",

View File

@ -1755,6 +1755,7 @@ describe('Gun', function(){
//expect(count['Alice']).to.be(1); //expect(count['Alice']).to.be(1);
//expect(count['Bob']).to.be(1); //expect(count['Bob']).to.be(1);
//expect(count['Alice Zzxyz']).to.be(1); //expect(count['Alice Zzxyz']).to.be(1);
if(done.c){ return } done.c = 1;
done(); done();
},200); },200);
} }
@ -3132,6 +3133,7 @@ describe('Gun', function(){
gun.path('alias').get(function(at){ gun.path('alias').get(function(at){
done.alias = done.alias || at.put.mark; done.alias = done.alias || at.put.mark;
}).path('mark').get(function(at){ }).path('mark').get(function(at){
//console.log("************", at.put);
setTimeout(function(){ setTimeout(function(){
done.mark = done.mark || at.put.pub; done.mark = done.mark || at.put.pub;
expect(Gun.val.rel.is(done.mark)).to.be('pub'); expect(Gun.val.rel.is(done.mark)).to.be('pub');
@ -3159,7 +3161,6 @@ describe('Gun', function(){
setTimeout(function(){ setTimeout(function(){
var gun2 = Gun(); var gun2 = Gun();
gun2.get('stef').path('address').val(function(data){ // Object {_: Object, country: "Netherlands", zip: "1766KP"} "adress" gun2.get('stef').path('address').val(function(data){ // Object {_: Object, country: "Netherlands", zip: "1766KP"} "adress"
//console.log("******", data);
done.a = true; done.a = true;
expect(data.country).to.be('Netherlands'); expect(data.country).to.be('Netherlands');
expect(data.zip).to.be('999999'); expect(data.zip).to.be('999999');
@ -3168,7 +3169,6 @@ describe('Gun', function(){
done(); done();
}); });
gun2.get('stef').val(function(data){ //Object {_: Object, address: Object} "stef" gun2.get('stef').val(function(data){ //Object {_: Object, address: Object} "stef"
//console.log("*****************", data);
done.s = true; done.s = true;
expect(data.name).to.be('Stef'); expect(data.name).to.be('Stef');
expect(data.address).to.be.ok(); expect(data.address).to.be.ok();
@ -3328,8 +3328,8 @@ describe('Gun', function(){
var app = gun.get('mult/times'); var app = gun.get('mult/times');
app.path('alias').path('mark').set(gun.get('asdf').put({ app.path('alias').path('mark').set(gun.get('ASDF').put({
pub: 'asdf', pub: 'ASDF',
alias: 'mark', alias: 'mark',
born: 1 born: 1
})); }));
@ -3343,7 +3343,7 @@ describe('Gun', function(){
app.path('alias').map().map().path('alias').on(function(data){ app.path('alias').map().map().path('alias').on(function(data){
done.two = data; done.two = data;
//console.log("alias 2!", data); //console.log("alias 2!", data);
expect(done.one).to.be("asdf"); expect(done.one).to.be("ASDF");
expect(done.two).to.be("mark"); expect(done.two).to.be("mark");
if(done.c){ return } done.c = 1; if(done.c){ return } done.c = 1;
done(); done();
@ -3358,7 +3358,7 @@ describe('Gun', function(){
Gun.on('put', {gun: gun, put: Gun.graph.ify({ Gun.on('put', {gun: gun, put: Gun.graph.ify({
alias: { alias: {
mark: { mark: {
pub: {_:{'#':'pub'}, pub: {_:{'#':'PUB'},
pub: 'asdf', pub: 'asdf',
alias: 'mark', alias: 'mark',
born: 1 born: 1
@ -3386,6 +3386,7 @@ describe('Gun', function(){
}); });
it('map with map function', function(done){ it('map with map function', function(done){
console.debug.i=0;
var gun = Gun(), s = 'map/mapfunc', u; var gun = Gun(), s = 'map/mapfunc', u;
var app = gun.get(s); var app = gun.get(s);
var list = app.get('list'); var list = app.get('list');
@ -3399,8 +3400,7 @@ describe('Gun', function(){
done(); done();
} }
}); });
list.set({name: 'alice', age: 27}); // on put, table-scan flag doesn't get set, but is needed for initial!??
list.set({name: 'alice', age: 27});
list.set({name: 'bob', age: 27}); list.set({name: 'bob', age: 27});
list.set({name: 'carl', age: 29}); list.set({name: 'carl', age: 29});
list.set({name: 'dave', age: 25}); list.set({name: 'dave', age: 25});
@ -3455,7 +3455,42 @@ describe('Gun', function(){
list.path('message').put('hello world'); // outputs "message: hello world" list.path('message').put('hello world'); // outputs "message: hello world"
list.path('message').put(null); // throws Uncaught TypeError: Cannot read property '#' of null list.path('message').put(null); // throws Uncaught TypeError: Cannot read property '#' of null
}); });
it('Check multi instance message passing', function(done){
try{ require('fs').unlinkSync('bdata') }catch(e){}
try{ require('fs').unlinkSync('ddata') }catch(e){}
Gun.on('out', function(msg){
//console.log("oye", msg);
this.to.next(msg);
var onGun = msg.gun.back(-1);
if(onGun === b) {
if(d){
//console.log("b can send to d....", Gun.obj.copy(msg));
d.on("in", msg);
}
} else if(onGun === d){
//console.log("d sends to b....", Gun.obj.copy(msg));
b.on("in", msg);
}
})
var b = Gun({file: "bdata"});
var d = null;
var bb = b.get("key");
bb.put({msg: "hello"});
d = Gun({file: "ddata"});
var db = d.get("key");
db.map().on(function(val,field){
//console.log("d key got val:", field, val)
expect(val).to.be('hello');
if(done.c){ return } done.c = 1;
setTimeout(function(){
done();
},1700);
});
});
return; return;
it.only('Custom extensions are chainable', function(done){ it.only('Custom extensions are chainable', function(done){
Gun.chain.filter = function(filter){ Gun.chain.filter = function(filter){
@ -3503,6 +3538,20 @@ describe('Gun', function(){
.val(function(yes){console.log("YES!", yes)}) .val(function(yes){console.log("YES!", yes)})
}); });
it.only('Check that events are called with multiple instances', function(done){
var gunA = Gun( { file : "A.json" } );
var gunB = Gun( { file : "B.json" });
var gunC = Gun( { file : "C.json" });
gunA.get( "some path A" ).map( (v,f)=>{ console.log( "event on A: ", f, v ) } );
gunB.get( "some path B" ).map( (v,f)=>{ console.log( "event on B: ", f, v ) } );
gunC.get( "some path C" ).map( (v,f)=>{ console.log( "event on C: ", f, v ) } );
gunA.get( "some path A" ).put( { simple:"message" } );
gunB.get( "some path B" ).put( { simple:"message" } );
gunC.get( "some path C" ).put( { simple:"message" } );
});
it.only('Make sure circular contexts are not copied', function(done){ it.only('Make sure circular contexts are not copied', function(done){
/* let's define an appropriate deep default database... */ /* let's define an appropriate deep default database... */
var dfltSansUsers = { 1: { name : "org1", sites : { 1: {name : "site1"} } } }; var dfltSansUsers = { 1: { name : "org1", sites : { 1: {name : "site1"} } } };

176
test/panic/b2s2s2b.js Normal file
View File

@ -0,0 +1,176 @@
var config = {
IP: require('ip').address(),
port: 8080,
servers: 2,
browsers: 2,
each: 12000,
burst: 1000,
wait: 1,
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 browsers = clients.excluding(servers);
describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +" server(s)!", function(){
//this.timeout(5 * 60 * 1000);
this.timeout(10 * 60 * 1000);
it("Servers have joined!", function(){
return servers.atLeast(config.servers);
});
it("GUN has spawned!", function(){
var tests = [], i = 0;
servers.each(function(client){
tests.push(client.run(function(test){
var env = test.props;
test.async();
try{ require('fs').unlinkSync(env.i+'data') }catch(e){}
var server = require('http').createServer(function(req, res){
res.end("I am "+ env.i +"!");
});
var port = env.config.port + env.i;
var Gun = require('gun');
var peers = [], i = env.config.servers;
while(i--){
var tmp = (env.config.port + (i + 1));
if(port != tmp){ // ignore ourselves
peers.push('http://'+ env.config.IP + ':' + tmp + '/gun');
}
}
console.log(port, " connect to ", peers);
var gun = Gun({file: env.i+'data', peers: peers, web: server});
server.listen(port, function(){
test.done();
});
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});
it(config.browsers +" browser(s) have joined!", function(){
console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
browsers.atLeast(1).then(function(){
browsers.run(function(test){
var env = test.props;
$('body').prepend("<button onclick='allopen()'>Open All Browsers</button>");
window.allopen = function(i){
if(env.config.browsers <= i){ return }
i = i || 1;
var win = window.open(location, '_blank');
win.focus();
setTimeout(function(){allopen(i+1)},0);
}
}, {config: config});
});
return browsers.atLeast(config.browsers);
});
it("Data was saved and synced across all browsers!", function(){
var tests = [], ids = {}, i = 0;
browsers.each(function(client, id){
ids[id] = 1;
});
browsers.each(function(client, id){
tests.push(client.run(function(test){
localStorage.clear();
var env = test.props;
test.async();
var peers = [], i = env.i;
//while(i--){
peers.push('http://'+ env.config.IP + ':' + (env.config.port + (i)) + '/gun');
//}
console.log("Connect to", peers);
var gun = Gun(peers);
var num = 0, total = 0, check = Gun.obj.map(env.ids, function(v,id,t){
var i = env.config.each;
while(i--){
t(id + (i + 1), 1);
total += 1;
}
});
var report = $("<div>").css({position: 'fixed', top: 0, right: 0, background: 'white', padding: 10}).text(num +" / "+ total +" Verified").prependTo('body');
var wait;
gun.get('test').map().on(function(data, key){
//$(log).text(key +": "+ data);
if(("Hello world, "+key+"!") === data){
if(check[key]){ num += 1 }
check[key] = 0;
report.text(num +" / "+ total +" Verified");
}
if(wait){ return }
wait = setTimeout(function(){
wait = false;
if(Gun.obj.map(check, function(still){
if(still){ return true }
})){ return }
console.log("SUCCESS");
test.done();
},10);
});
setTimeout(function(){
console.log("<<<<< START >>>>>");
var i = 0, burst = false, to = setInterval(function go(){
if(!burst){
burst = env.config.burst;
while(--burst){
go();
}
burst = false;
return;
}
if(env.config.each <= i){
clearTimeout(to);
return;
}
i += 1;
var p = env.id + i;
gun.get('test').get(p).put('Hello world, '+ p +'!');
}, env.config.wait);
},500);
}, {i: i += 1, id: id, ids: ids, config: config}));
});
return Promise.all(tests);
});
it("All finished!", function(done){
console.log("Done! Cleaning things up...");
setTimeout(function(){
done();
},1000);
});
after("Everything shut down.", function(){
browsers.run(function(){
//location.reload();
//setTimeout(function(){
//}, 15 * 1000);
});
return servers.run(function(){
process.exit();
});
});
});

View File

@ -2,8 +2,8 @@ var config = {
IP: require('ip').address(), IP: require('ip').address(),
port: 8080, port: 8080,
servers: 1, servers: 1,
browsers: 2, browsers: 4,
each: 500, each: 1500,
wait: 1, wait: 1,
route: { route: {
'/': __dirname + '/index.html', '/': __dirname + '/index.html',
@ -87,9 +87,8 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
}); });
// Launch the server and start gun! // Launch the server and start gun!
var Gun = require('gun'); var Gun = require('gun');
var gun = Gun({file: env.i+'data.json'});
// Attach the server to gun. // Attach the server to gun.
//gun.wsp(server); var gun = Gun({file: env.i+'data', web: server});
server.listen(env.config.port + env.i, function(){ server.listen(env.config.port + env.i, function(){
// This server peer is now done with the test! // This server peer is now done with the test!
// It has successfully launched. // It has successfully launched.
@ -154,6 +153,7 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
browsers.each(function(client, id){ browsers.each(function(client, id){
// for every browser, run the following code: // for every browser, run the following code:
tests.push(client.run(function(test){ tests.push(client.run(function(test){
//var audio = new Audio('https://www.nasa.gov/mp3/640170main_Roger%20Roll.mp3');audio.addEventListener('ended', function() {this.currentTime = 0;this.play();}, false);audio.play(); // testing if audio prevents Chrome throttle?
localStorage.clear(); // Clean up anything from before. localStorage.clear(); // Clean up anything from before.
var env = test.props; var env = test.props;
// Get access to the "outer scope" which has the browser IDs // Get access to the "outer scope" which has the browser IDs
@ -164,9 +164,10 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
while(i--){ while(i--){
// For the total number of servers listed in the configuration // For the total number of servers listed in the configuration
// Add their URL into an array. // Add their URL into an array.
peers.push('http://'+ env.config.IP + ':' + (env.config.port + (i + 1))); peers.push('http://'+ env.config.IP + ':' + (env.config.port + (i + 1)) + '/gun');
} }
// Pass all the servers we want to connect to into gun. // Pass all the servers we want to connect to into gun.
//var gun = Gun();
var gun = Gun(peers); var gun = Gun(peers);
// Now we want to create a list // Now we want to create a list
// of all the messages that WILL be sent // of all the messages that WILL be sent
@ -195,18 +196,19 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
//var el = $('#'+key).length ? $('#'+key) : $('<div>'); //var el = $('#'+key).length ? $('#'+key) : $('<div>');
// log the data out to, so we can visually see our test. // log the data out to, so we can visually see our test.
//$(log).append(el.attr('id', key).text(key +": "+ data)); //$(log).append(el.attr('id', key).text(key +": "+ data));
$(log).text(key +": "+ data); // DOM updates thrash performance, try this.
// Scroll down with the logging.
//$('body').stop(true).animate({scrollTop: $(log).height()});
// Now, make sure the received data // Now, make sure the received data
// matches exactly the data we EXPECT // matches exactly the data we EXPECT
if(("Hello world, "+key+"!") === data){ if(("Hello world, "+key+"!") === data){
// if it does, we can "check off" record // if it does, we can "check off" record
// Bump the total number of verified items and update the UI.
if(check[key]){ num += 1 }
// from our verify todo list. // from our verify todo list.
check[key] = 0; check[key] = 0;
// Bump the total number of verified items and update the UI.
num += 1;
report.text(num +" / "+ total +" Verified"); report.text(num +" / "+ total +" Verified");
} }
// Scroll down with the logging.
//$('body').stop(true).animate({scrollTop: $(log).height()});
// This next part is important: // This next part is important:
if(Gun.obj.map(check, function(still){ if(Gun.obj.map(check, function(still){
// IF THERE ARE ANY RECORDS STILL LEFT TO BE VERIFIED // IF THERE ARE ANY RECORDS STILL LEFT TO BE VERIFIED
@ -220,14 +222,14 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
test.done(); test.done();
}); });
// But we have to actually tell the browser to save data! // But we have to actually tell the browser to save data!
var i = 0, to = setTimeout(function go(){ var i = 0, to = setInterval(function go(){
// Cool, make a recursive function // Cool, make a recursive function
// that keeps going until we've saved each message. // that keeps going until we've saved each message.
if(env.config.each <= i){ if(env.config.each <= i){
clearTimeout(to); clearTimeout(to);
return; return;
} }
to = setTimeout(go, env.config.wait * Math.random()); // add a little jitter. //to = setTimeout(go, env.config.wait * Math.random()); // add a little jitter.
i += 1; i += 1;
var p = env.id + i; var p = env.id + i;
// And actually save the data with gun, // And actually save the data with gun,