Merge pull request #1 from PsychoLlama/master

Automated browser test runners/tab runners
This commit is contained in:
Jesse Gibson
2015-12-22 13:41:21 -07:00
11 changed files with 384 additions and 2 deletions

BIN
.DS_Store vendored

Binary file not shown.

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@
/bower_components/
/node_modules/
level/
.DS_Store

5
README.md Normal file
View File

@@ -0,0 +1,5 @@
# Panic
See how gun handles under different conditions
### *under development*

35
browser.js Normal file
View File

@@ -0,0 +1,35 @@
/*globals patch*/
var Browser;
(function () {
'use strict';
Browser = function (opt) {
if (!(this instanceof Browser)) {
return new Browser(opt);
}
var browser = this;
browser.opt = opt;
opt.done.cb = (function () {
var cb = opt.done.cb;
return function (opt) {
if (cb) {
cb.apply(this, arguments);
}
browser.close();
};
}());
browser.window = window.open('./', browser.opt.id);
browser.window.addEventListener('load', function () {
browser.window.test(browser.opt);
});
};
Browser.prototype = {
constructor: Browser,
close: function () {
this.window.close();
return this;
}
};
}());

42
done.js Normal file
View File

@@ -0,0 +1,42 @@
/*globals Gun, console, stats */
/*
check it against opt.id
make sure everything is fabulous
begin with a timeout + interval,
restart on each acknowledgment
*/
function finisher() {
'use strict';
return (function () {
var timeout;
function done(db, opt) {
var saved = 0;
opt.requests.end = Gun.time.is();
function scan(obj) {
if (obj.id === opt.id) {
saved += 1;
}
}
db.path(opt.path).each(scan, function () {
stats(opt, saved);
opt.done.cb(opt);
});
}
return function (db, opt) {
clearTimeout(timeout);
timeout = setTimeout(function () {
done(db, opt);
}, opt.interval + opt.done.timeout);
};
}());
}

View File

@@ -5,6 +5,7 @@
<title>Battle Test</title>
<link rel="stylesheet" href="index.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
</head>
<body>
@@ -65,7 +66,13 @@
Any help on building this out would be appreciated!
</p>
<script src="gun.js"></script>
<script src="polyfill.js"></script>
<script src="statistics.js"></script>
<script src="done.js"></script>
<script src="node_modules/mavis/index.js"></script>
<script src="patch.js"></script>
<script src="index.js"></script>
<script src="browser.js"></script>
</body>
</html>

View File

@@ -1,2 +1,57 @@
/*globals Gun, console */
var gun = new Gun('http://localhost:8080/gun');
/*globals Gun, console, patch, finisher, stats */
var test;
test = function (opt) {
'use strict';
opt = patch(opt);
var gun, resetDoneTimer, db, confirmed = {};
resetDoneTimer = finisher();
gun = new Gun(opt.peers);
db = gun.get(opt.key).set();
function ack(num) {
return function (err, ok) {
if (confirmed[num]) {
return;
}
opt.requests[num - 1].end = Gun.time.is();
confirmed[num] = true;
opt.progress(opt, num);
resetDoneTimer(db, stats(opt));
};
}
function run(num) {
var cb, packet = opt.packet();
cb = ack(num);
opt.requests[num - 1] = {
start: packet.time
};
db.path(opt.path).set(packet, cb);
if (num === opt.packets) {
return;
}
setTimeout(function () {
run(num + 1);
}, opt.interval);
return opt;
}
resetDoneTimer(db, opt);
return run(1);
};
if (typeof window !== 'undefined') {
if (window.options) {
test(window.options);
}
}

30
package.json Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "panic",
"version": "0.1.0",
"description": "Test gun against a storm of requests",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/PsychoLlama/panic.git"
},
"keywords": [
"gun",
"gundb",
"test",
"testing",
"distributed"
],
"author": "Jesse Gibson <jesse@gundb.io> (http://techllama.com)",
"license": "(Zlib OR MIT OR Apache-2.0)",
"bugs": {
"url": "https://github.com/PsychoLlama/panic/issues"
},
"homepage": "https://github.com/PsychoLlama/panic#readme",
"dependencies": {
"gun-level": "^2.1.1"
}
}

109
patch.js Normal file
View File

@@ -0,0 +1,109 @@
/*globals Gun, type, console*/
/*
Return an object like this:
return {
expect: Object,
done: Function,
progress: Function,
interval: Number,
peers: Array,
packets: Number,
id: String,
key: String,
path: String,
packet: Function
};
*/
var patch;
(function () {
'use strict';
var random = Gun.text.random;
function is(data, expected) {
var string, error, actual = type(data);
if (actual !== expected) {
string = JSON.stringify(data);
error = 'Expected ' + expected + ', was ' + actual + ': ' + string;
throw new TypeError(error);
}
return true;
}
function or(obj, prop, val) {
return (obj[prop] = obj[prop] || val);
}
function done(opt) {
or(opt, 'done', {});
or(opt.done, 'cb', function () {
console.log('No finishing callback');
});
or(opt.done, 'timeout', 2000);
is(opt.done, 'object');
is(opt.done.timeout, 'number');
is(opt.done.cb, 'function');
}
function packet(opt) {
// wrap the packet function
// set time and id for
// every returned object
opt.packet = (function () {
var makePacket = opt.packet || function () {
return random();
};
return function () {
return {
data: makePacket(),
time: Gun.time.is(),
id: opt.id
};
};
}());
is(opt.packet(), 'object');
}
patch = function (opt) {
var url = location.protocol + '//';
url += location.host;
url += '/gun';
opt = opt || {};
opt.interval = opt.interval || 0;
opt.peers = opt.peers || [url];
opt.packets = opt.packets || 50;
opt.id = opt.id || random(10);
opt.key = opt.key || random(15);
opt.path = opt.path || random(5);
opt.requests = [];
opt.requests.start = Gun.time.is();
or(opt, 'progress', function (opt, num) {
console.log('Saved', num);
});
done(opt);
packet(opt);
is(opt.key, 'string');
is(opt.interval, 'number');
is(opt.peers, 'array');
is(opt.packets, 'number');
is(opt.id, 'string');
is(opt.path, 'string');
is(opt.progress, 'function');
if (opt.packets < 0) {
throw new RangeError("Negative packets? Are you crazy?");
}
return opt;
};
}());

61
polyfill.js Normal file
View File

@@ -0,0 +1,61 @@
/*globals Gun, console*/
Object.keys = Object.keys || function (obj) {
'use strict';
var key, keys = [];
for (key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys;
};
Object.values = Object.values || function (obj) {
'use strict';
return Object.keys(obj).map(function (key) {
return obj[key];
});
};
var setImmediate = setImmediate || function (cb) {
'use strict';
setTimeout(cb, Infinity);
};
console.log = (function () {
'use strict';
var peersError, log = console.log;
peersError = 'Warning! You have no peers to connect to!';
return function (msg) {
if (msg === peersError) {
return;
}
log.apply(console, arguments);
};
}());
Gun.chain.each = function (cb, end) {
'use strict';
var n = function () {},
count = 0,
props = [],
gun = this;
cb = cb || n;
end = end || n;
gun.val(function (list) {
var args = Array.prototype.slice.call(arguments);
Gun.is.node(list, function (n, prop) {
count += 1;
props.push(prop);
});
props.forEach(function (prop) {
gun.path(prop).val(function (val, key) {
count -= 1;
cb.apply(this, arguments);
if (!count) {
end.apply(this, args);
}
});
});
});
return gun;
};

37
statistics.js Normal file
View File

@@ -0,0 +1,37 @@
/*globals Gun*/
function stats(opt, saved) {
'use strict';
var average, slowest, fastest, elapsed, acks = [];
fastest = null;
slowest = null;
average = 0;
acks = opt.requests.filter(function (request) {
return Boolean(request.end);
});
acks.forEach(function (ack) {
var time = ack.end - ack.start;
if (time > slowest) {
slowest = time;
}
if (time < fastest || !fastest) {
fastest = time;
}
average += (ack.end - ack.start);
});
average = average / acks.length;
elapsed = (opt.requests.end - opt.requests.start) - opt.done.timeout - opt.interval;
opt.stats = {
'average latency': average,
requested: opt.packets,
acknowledged: acks.length,
'slowest response': slowest,
'fastest response': fastest,
'total elapsed': elapsed || Gun.time.is() - opt.requests.start
};
if (saved !== undefined) {
opt.stats.confirmed = saved;
}
return opt;
}