+
+
+
+
+
+
+
+
+
diff --git a/test/panic/infinite-scroll/index.js b/test/panic/infinite-scroll/index.js
new file mode 100644
index 00000000..99f2a216
--- /dev/null
+++ b/test/panic/infinite-scroll/index.js
@@ -0,0 +1,226 @@
+var config = {
+ IP: require('ip').address(),
+ port: 8765,
+ servers: 1,
+ browsers: 1,
+ each: 1500,
+ wait: 1,
+ route: {
+ '/': __dirname + '/index.html',
+ '/ScrollWindow.js': __dirname + '/../../../examples/infinite-scroll/ScrollWindow.js',
+ '/index.js': __dirname + '/../../../examples/infinite-scroll/index.js',
+ '/style.css': __dirname + '/../../../examples/infinite-scroll/style.css',
+ '/gun.js': __dirname + '/../../../gun.js',
+ '/jquery.js': __dirname + '/../../../examples/jquery.js'
+ }
+}
+
+/*
+ Welcome, person!
+ You have found the test that causes gun to PANIC with load!
+ Above are options to configure, the only ones useful are:
+ - browsers // number of browsers you want to load test across.
+ - each // the number of messages each browser should sync.
+ This test is less than 200 lines of code (without comments)!
+ However, if you aren't familiar with PANIC - you are in for a surprise!
+ I'm Plublious, and I shall be your guide!
+*/
+
+// First we need to create a PANIC server.
+// Each device/browser in the distributed system we are testing connects to it.
+// It then coordinates these clients to cause chaos in the distributed system.
+// Cool huh?
+var panic = require('panic-server');
+panic.server().on('request', function(req, res){ // Static server
+ config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
+}).listen(config.port); // Start panic server.
+
+// In order to tell the clients what to do,
+// We need a way to reference all of them.
+var clients = panic.clients;
+
+// Some of the clients may be NodeJS servers on different machines.
+// PANIC manager is a nifty tool that lets us remotely spawn them.
+var manager = require('panic-manager')();
+manager.start({
+ clients: Array(config.servers).fill().map(function(u, i){ // Create a bunch of servers.
+ return {
+ type: 'node',
+ port: config.port + (i + 1) // They'll need unique ports to start their servers on, if we run the test on 1 machine.
+ }
+ }),
+ panic: 'http://' + config.IP + ':' + config.port // Auto-connect to our panic server.
+});
+
+// Now lets divide our clients into "servers" and "browsers".
+var servers = clients.filter('Node.js');
+var browsers = clients.excluding(servers);
+
+// Sweet! Now we can start the tests.
+// PANIC works with Mocha and other testing libraries!
+// So it is easy to use PANIC.
+
+describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +" server(s)!", function(){
+
+ // We'll have to manually launch the browsers,
+ // So lets up the timeout so we have time to do that.
+ this.timeout(5 * 60 * 1000);
+
+ it("Servers have joined!", function(){
+ // Alright, lets wait until enough gun server peers are connected.
+ return servers.atLeast(config.servers);
+ });
+
+ it("GUN has spawned!", function(){
+ // Once they are, we need to actually spin up the gun server.
+ var tests = [], i = 0;
+ servers.each(function(client){
+ // for each server peer, tell it to run this code:
+ tests.push(client.run(function(test){
+ // NOTE: Despite the fact this LOOKS like we're in a closure...
+ // it is not! This code is actually getting run
+ // in a DIFFERENT machine or process!
+ var env = test.props;
+ // As a result, we have to manually pass it scope.
+ test.async();
+ // Clean up from previous test.
+ try{ require('fs').unlinkSync(env.i+'data.json') }catch(e){}
+ var server = require('http').createServer(function(req, res){
+ res.end("I am "+ env.i +"!");
+ });
+ // Launch the server and start gun!
+ var Gun = require('gun');
+ // Attach the server to gun.
+ var gun = Gun({file: env.i+'data', web: server, localStorage: false});
+ server.listen(env.config.port + env.i, function(){
+ // This server peer is now done with the test!
+ // It has successfully launched.
+ test.done();
+ });
+ }, {i: i += 1, config: config}));
+ });
+ // NOW, this is very important:
+ // Do not proceed to the next test until
+ // every single server (in different machines/processes)
+ // have ALL successfully launched.
+ return Promise.all(tests);
+ });
+
+ it(config.browsers +" browser(s) have joined!", function(){
+ // Okay! Cool. Now we can move on to the next step...
+ console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ // Which is to manually open up a bunch of browser tabs
+ // and connect to the PANIC server in the same way
+ // the NodeJS servers did.
+
+ // However! We're gonna cheat...
+ browsers.atLeast(1).then(function(){
+ // When there is at least one browser opened, tell it to run this code:
+ browsers.run(function(test){
+ // NOTE: This closure is now being run IN THE BROWSER.
+ // This code is not server side code, despite the fact
+ // that we've written it on the server. It is not.
+ // Mind blowing, right?
+ var env = test.props;
+ }, {config: config});
+ });
+ // Cool! Once that is done...
+ // WAIT until all those browser tabs
+ // have connected to the PANIC server
+ // THEN move onto the next step
+ // where we will cause chaos!
+ return browsers.atLeast(config.browsers);
+ });
+
+ it("Data was saved and synced across all browsers!", function(){
+ // This is where it gets good!
+ var tests = [], ids = {}, i = 0;
+ // Let us create a list of all the browsers IDs connected.
+ // This will later let each browser check against every other browser.
+ browsers.each(function(client, id){
+ ids[id] = 1;
+ });
+ browsers.each(function(client, id){
+ // for every browser, run the following code:
+ 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.
+ var env = test.props;
+ // Get access to the "outer scope" which has the browser IDs
+ // as well as other configuration information.
+ test.async();
+ // Now we want to connect to every gun server peer...
+ var peers = [], i = env.config.servers;
+ while(i--){
+ // For the total number of servers listed in the configuration
+ // Add their URL into an array.
+ peers.push('http://'+ env.config.IP + ':' + (env.config.port + (i + 1)) + '/gun');
+ }
+ // Pass all the servers we want to connect to into gun.
+ //var gun = Gun();
+ var gun = Gun(peers);
+ // Now we want to create a list
+ // of all the messages that WILL be sent
+ // according to the expected configuration.
+ // This is equal to...
+ var num = 0, total = env.config.each, check = {};
+ var report = $("
").css({position: 'fixed', top: 0, right: 0, background: 'white', padding: 10}).text(num +" / "+ total +" Verified").prependTo('body');
+ // Add a nifty UI that tells us how many messages have been verified.
+ // FINALLY, tell gun to subscribe to every record
+ // that is is/will be saved to this table.
+
+ var countAndScroll = () => {
+ $('.post b').each(function() {
+ var t = $(this).text();
+ if (check[t]) return;
+ num += 1;
+ report.text(num +" / "+ total +" Verified");
+ if (num === total) {
+ test.done();
+ }
+ check[t] = true;
+ });
+ $(window).scrollTop($(window).height());
+ }
+ window.onRender = elements => {
+ countAndScroll();
+ };
+
+ $('#number').val(env.config.each);
+ $('#generate button').click();
+ countAndScroll();
+ }, {i: i += 1, id: id, ids: ids, config: config}));
+ });
+ // YAY! We're finally done.
+ // IF AND ONLY IF
+ // EVERY SINGLE BROWSER
+ // HAS VERIFIED
+ // EVERY OTHER BROWSERS' data.
+ // If they are ALL done, go to the next step.
+ return Promise.all(tests);
+ });
+
+ after("Everything shut down.", function(){
+ // which is to shut down all the browsers.
+ browsers.run(function(){
+ setTimeout(function(){
+ location.reload();
+ }, 15 * 1000);
+ });
+ // And shut down all the servers.
+ return servers.run(function(){
+ process.exit();
+ });
+ });
+})
+// THE END!
+// Congrats, wasn't that epic?
+// Or still confused how a single 200 LOC test file
+// Is running correctness verification tests
+// across an entire distributed system of devices/browsers?
+// Well, jump on https://gitter.im/amark/gun !
+
+// Think adding tests like this to your work place would be bomb awesome?
+// We totally sell PANIC training, licenses, and support!
+// Please reach out to hi@gunDB.io if you are interested
+// in purchasing consulting or services for PANIC.
diff --git a/test/panic/level.js b/test/panic/level.js
new file mode 100644
index 00000000..f4457327
--- /dev/null
+++ b/test/panic/level.js
@@ -0,0 +1,216 @@
+const panic = require('panic-server');
+const clients = panic.clients;
+const manager = require('panic-manager')();
+const opts = { radisk: false, localStorage: false, file: false };
+
+require('events').EventEmitter.defaultMaxListeners = Infinity;
+
+const config = {
+ ip : require('ip').address(),
+ port : 8765,
+ servers : 3,
+ route : {
+ '/' : __dirname + '/index.html',
+ '/gun.js' : __dirname + '/../../gun.js',
+ '/jquery.js' : __dirname + '/../../examples/jquery.js'
+ }
+};
+
+const srv = panic.server();
+srv.on('request', (req, res) => {
+ config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
+}).listen(config.port);
+
+manager.start({
+ clients: Array(config.servers).fill().map((u,i) => ({
+ type: 'node',
+ port: config.port + i + 1,
+ })),
+ panic: `http://${config.ip}:${config.port}`
+});
+
+const servers = clients.filter('Node.js');
+const server = servers.pluck(1);
+const alice = servers.excluding(server).pluck(1);
+const bob = servers.excluding(server).excluding(alice).pluck(1);
+
+describe('Make sure the leveldb storage engine works', function() {
+ this.timeout(5 * 60 * 60 * 1000);
+
+ it("servers have joined!", function() {
+ return servers.atLeast(config.servers);
+ });
+
+ it("GUN started!", function() {
+ return server.run(function(test) {
+ test.async();
+ const {config,opts} = test.props;
+
+ const leveldown = require('leveldown');
+ const encode = require('encoding-down');
+ const levelup = require('levelup');
+
+ if (require('fs').existsSync('./lvldata')) {
+ console.error('Please delete previous data first!');
+ return;
+ }
+
+ // Initialize leveldb
+ // const level = global.level = levelup(leveldown('./lvldata'));
+ const level = global.level = levelup(encode(leveldown('./lvldata'), { valueEncoding: 'json' }));
+
+ // Load the libraries under test
+ const Gun = require('../../../index');
+ const debug = require('../../../lib/level');
+
+ // // Add debug message
+ // debug.on('create', () => console.log('LEVEL CREATE'));
+ // debug.on('get' , key => console.log('LEVEL GET', key));
+ // debug.on('put' , (key, value) => console.log('LEVEL PUT', key, value));
+ // // debug.on('list', () => console.log('LEVEL LIST'));
+ // debug.on('error' , err => console.log('LEVEL ERROR', err));
+
+ // Track state (so we can wait on put, it's called late by radisk)
+ global.state = 0;
+ debug.on('put', () => global.state++);
+
+ // Create server
+ opts.web = require('http').createServer(function(req, res) {
+ res.end("Number five is alive!");
+ });
+
+ // Initialize gun & start server
+ const gun = global.gun = Gun({ ...opts, level });
+ opts.web.listen(config.port + 1, function() {
+ test.done();
+ });
+
+ }, {config,opts});
+ });
+
+ it("Alice saves data", function() {
+ return alice.run(function(test) {
+ test.async();
+ const {config,opts} = test.props;
+ const Gun = require('../../../index');
+
+ // Start gun
+ const gun = global.gun = Gun({
+ ...opts,
+ peers: 'http://'+ config.ip + ':' + (config.port + 1) + '/gun',
+ lack : 1000 * 60 * 60,
+ });
+
+ // Save data
+ // Timeout allows callbacks to fire before server read
+ const ref = gun.get('asdf');
+ ref.put({ hello: 'world' });
+ setTimeout(() => {
+ test.done();
+ }, 1);
+ }, {config,opts});
+ });
+
+ it('Server read data', function() {
+ return server.run(function(test) {
+ test.async();
+
+ // Read data (triggers fetch from alice + write to disk)
+ const ref = gun.get('asdf');
+ ref.on(data => {
+ if (data.hello !== 'world') {
+ return test.fail('Invalid data returned');
+ }
+ ref.off();
+ test.done();
+ });
+
+ });
+ });
+
+ it('Wait for server to store', function() {
+ return server.run(function(test) {
+ test.async();
+ setTimeout(function awaitState() {
+ if (global.state < 2) return setTimeout(awaitState, 50);
+ test.done();
+ }, 50);
+ });
+ });
+
+ it('Close all original running nodes', function() {
+ clients.pluck(2).run(function() {
+ if (global.level) {
+ global.level.close(function() {
+ process.exit();
+ });
+ } else {
+ process.exit();
+ }
+ });
+ });
+
+ it('Start bob', function() {
+ return bob.run(function(test) {
+ test.async();
+ const {config,opts} = test.props;
+
+ const leveldown = require('leveldown');
+ const encode = require('encoding-down');
+ const levelup = require('levelup');
+
+ // Initialize gun opts
+ const level = global.level = levelup(encode(leveldown('./lvldata'), { valueEncoding: 'json' }));
+
+ // Load the libraries under test
+ const Gun = require('../../../index');
+ const debug = require('../../../lib/level');
+
+ // // Add debug messages
+ // debug.on('get', key => console.log('LEVEL GET', key));
+ // debug.on('put', (key, value) => console.log('LEVEL PUT', key, value));
+ // // debug.on('list', () => console.log('LEVEL LIST'));
+ // debug.on('error', err => console.log('LEVEL ERROR', err));
+
+ // Create server
+ opts.web = require('http').createServer((req, res) => {
+ res.end("Number five is alive!");
+ });
+
+ // Initialize gun & start server
+ const gun = global.gun = Gun({ ...opts, level });
+ opts.web.listen(config.port + 1, () => {
+ test.done();
+ });
+ }, {config,opts});
+ });
+
+ it('Bob read', function() {
+ return bob.run(function(test) {
+ test.async();
+
+ // Read data
+ const ref = gun.get('asdf');
+ ref.on(data => {
+ if (data.hello !== 'world') {
+ return test.fail('Invalid data returned');
+ }
+ ref.off();
+ test.done();
+ });
+
+ });
+ });
+
+ it('Shutdown bob', function() {
+ return clients.run(function() {
+ process.exit()
+ });
+ });
+
+ it("All finished!", function(done) {
+ srv.close();
+ done();
+ });
+
+});
diff --git a/test/panic/lexical.js b/test/panic/lexical.js
new file mode 100644
index 00000000..fac94fa6
--- /dev/null
+++ b/test/panic/lexical.js
@@ -0,0 +1,452 @@
+/**
+ * RAD Lexical search test
+ *
+ * What we want here: (1) Superpeer and (n) peers
+ * - The Superpeer have a graph with `key(timestamp)->value(value)`
+ * - The peer will run an amount of queries and the total of results are the 'expected results'.
+ *
+ * Tip: to run this `mocha test/panic/lexical`
+ *
+ */
+var config = {
+ IP: require('ip').address(),
+ port: process.env.PORT ? parseInt(process.env.PORT) : 8765,
+ servers: 1,
+ browsers: 1,
+ route: {
+ '/': __dirname + '/index.html',
+ '/gun.js': __dirname + '/../../gun.js',
+ '/gun/lib/radix.js': __dirname + '/../../lib/radix.js',
+ '/gun/lib/radisk.js': __dirname + '/../../lib/radisk.js',
+ '/gun/lib/store.js': __dirname + '/../../lib/store.js',
+ '/gun/lib/rindexed.js': __dirname + '/../../lib/rindexed.js',
+ '/jquery.js': __dirname + '/../../examples/jquery.js'
+ },
+ wait_map: 700
+}
+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 server = global.server = servers.pluck(1);
+var server2 = servers.excluding(server).pluck(1);
+var browsers = clients.excluding(servers);
+var alice = browsers.pluck(1);
+var bob = browsers.excluding(alice).pluck(1);
+var john = browsers.excluding(alice).excluding(bob).pluck(1);
+
+describe('RAD Lexical search Test! ', function() {
+ this.timeout(5 * 60 * 1000);
+ // this.timeout(10 * 60 * 1000);
+ it('Servers have joined! ', function() {
+ return servers.atLeast(config.servers);
+ });
+ it('GUN server started! ', function() {
+ return server.run(function(test) {
+ var env = test.props;
+ test.async();
+ try { require('fs').unlinkSync('radata_test_lexical_' + env.i) } catch (e) {}
+ try { require('fs').unlinkSync('radata_test_lexical_' + (env.i + 1)) } catch (e) {}
+ var port = env.config.port + env.i;
+ var server = require('http').createServer(function(req, res) { res.end("I am " + env.i + "!"); });
+ var Gun = global.Gun = require('gun');
+ var gun = global.gun = Gun({
+ axe: false,
+ multicast: false,
+ web: server,
+ file: 'radata_test_lexical_' + env.i,
+ //radisk:false, localStorage:false
+ });
+ server.listen(port, function() {
+ test.done();
+ });
+ }, {
+ i: 1,
+ config: config
+ });
+ });
+ it('Create graph with all days of year 2020', function() {
+ return server.run(function(test) {
+ test.async();
+ var j = 0;
+ graph = gun._.graph, timenode = {}, start = new Date('2020-01-01T00:00:00Z'), end = new Date('2020-12-31T23:59:59Z'), startt = start.getTime(), endt = end.getTime(), p = startt;
+ var ref = global.ref = gun.get('timenode');
+ while (p <= endt) { //console.log('.... >>> ', p, ++j, new Date(p).toISOString());
+ var t = new Date(p);
+ var ts = t.toISOString();
+ var soul = 'timeline_' + ts;
+ var d = { msg: ' datetime ' + ts };
+ var n = gun.get(soul).put(d);
+ ref.get(ts).put(n);
+
+ p = p + (24 * 60 * 60 * 1000); //24h
+ }
+ setTimeout(function() { /// wait a while for the .put
+ test.done();
+ }, 1000);
+ });
+ });
+ it('Query server - Beetween(< item <) ', function() {
+ var i=0;
+ return server.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '>': '2020-02-01', '<': '2020-02-26' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 25; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query server - Beetween(< item <): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes.');
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ });
+ });
+ it('Query server - Higher(>) ', function() {
+ var i=0;
+ return server.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '>': '2020-12-01' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 31; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query server - Higher(>): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ });
+ });
+ it('Query server - Lower(<) ', function() {
+ var i=0;
+ return server.run(function(test) {
+ test.async();
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '<': '2020-02-06' } };
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 37; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query server - Lower(<): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ });
+ });
+ it('Query server - Exact match(=) ', function() {
+ var i=0;
+ return server.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '=': '2020-03-01T00:00:00.000Z' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 1; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query server - Exact match(=): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ });
+ });
+ it('Query server - Prefix match(*) ', function() {
+ var i=0;
+ return server.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '*': '2020-10-' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 31; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query server - Prefix match(*): ', results_unique.length, results_unique);
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ });
+ });
+
+ 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) {
+ test.async();
+ localStorage.clear();
+ console.log('Clear localStorage!!!');
+// ['/gun/lib/radix.js', '/gun/lib/radisk.js', '/gun/lib/store.js', '/gun/lib/rindexed.js'].map(function(src) {
+// var script = document.createElement('script');
+// script.setAttribute('src', src);
+// document.head.appendChild(script);
+// });
+
+ var env = test.props;
+ var opt = {
+ peers: ['http://' + env.config.IP + ':' + (env.config.port + 1) + '/gun'],
+ localStorage: false
+ };
+ var pid = location.hash.slice(1);
+ if (pid) {
+ opt.pid = pid;
+ }
+ Gun.on('opt', function(ctx) {
+ this.to.next(ctx);
+ ctx.on('hi', function(opt) {
+ document.title = 'RAD test PID: ' + this.on.opt.pid;
+ });
+ });
+ setTimeout(function() {
+ var gun = window.gun = Gun(opt);
+ var ref = window.ref = gun.get('timenode');
+ test.done();
+ }, 1000);
+ }, {
+ i: i += 1,
+ config: config
+ }));
+ });
+ return Promise.all(tests);
+ });
+
+ it('Query browser - Beetween(< item <) ', function() {
+ var tests = [], i = 0;
+ browsers.each(function(client, id) {
+ tests.push(client.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.'); }, 6000);
+ var results = [];
+ var query = { '%': 100000, '.': { '>': '2020-06-01', '<': '2020-09-01' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 30+31+31; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query browser - Beetween(< item <): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, { i: i += 1, config: config }));
+ });
+ return Promise.all(tests);
+ });
+ it('Query browser - Higher(>) ', function() {
+ var tests = [], i = 0;
+ browsers.each(function(client, id) {
+ tests.push(client.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '>': '2020-11-01' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 61; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query browser - Higher(>): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ }));
+ });
+ return Promise.all(tests);
+ });
+ it('Query browser - Lower(<) ', function() {
+ var tests = [], i = 0;
+ browsers.each(function(client, id) {
+ tests.push(client.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '<': '2020-02-05' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ var len = 35; /// expected number of results
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query browser - Lower(<): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ }));
+ });
+ return Promise.all(tests);
+ });
+ it('Query browser - Exact match(=) ', function() {
+ var tests = [], i = 0;
+ browsers.each(function(client, id) {
+ tests.push(client.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '=': '2020-06-01T00:00:00.000Z' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 1; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query browser - Exact match(=): ', results_unique.length, results_unique.join(', '));
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ }));
+ });
+ return Promise.all(tests);
+ });
+ it('Query browser - Prefix match(*) ', function() {
+ var tests = [], i = 0;
+ browsers.each(function(client, id) {
+ tests.push(client.run(function(test) {
+ var env = test.props;
+ var t = setTimeout(function() { test.fail('Error: No response.');}, 5000);
+ var results = [];
+ var query = { '%': 100000, '.': { '*': '2020-10-' } };
+ test.async();
+ ref.get(query).map().once(function(v, k) {
+ if (k && v) { results.push(k); }
+ });
+ var t2 = setTimeout(function() {
+ var len = 31; /// expected number of results
+ var results_unique = results.filter(function(v, i, a) { return a.indexOf(v) === i; }).sort();
+ clearTimeout(t);
+ if (results_unique.length === len) {
+ test.done();
+ } else {
+ console.log('RESULTS Query browser - Prefix match(*): ', results_unique.length, results_unique);
+ test.fail('Error: get ' + results_unique.length + ' attributes istead of '+len);
+ }
+ }, env.config.wait_map);
+ }, {
+ i: i += 1,
+ config: config
+ }));
+ });
+ return Promise.all(tests);
+ });
+
+ ////////////////////////////////
+ it("Wait...", function(done){
+ setTimeout(done, 3000);
+ });
+ 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();
+ });
+ });
+});
diff --git a/test/panic/livestream.js b/test/panic/livestream.js
index f9fe1c95..6120f369 100644
--- a/test/panic/livestream.js
+++ b/test/panic/livestream.js
@@ -82,7 +82,7 @@ describe("Broadcast Video", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -180,11 +180,7 @@ describe("Broadcast Video", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/load.js b/test/panic/load.js
index 06cde4e7..799c34b8 100644
--- a/test/panic/load.js
+++ b/test/panic/load.js
@@ -105,8 +105,8 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
it(config.browsers +" browser(s) have joined!", function(){
// Okay! Cool. Now we can move on to the next step...
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
- // Which is to manually open up a bunch of browser tabs
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
+ // Which is to automatically or manually open up a bunch of browser tabs
// and connect to the PANIC server in the same way
// the NodeJS servers did.
@@ -249,7 +249,7 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
after("Everything shut down.", function(){
// which is to shut down all the browsers.
- browsers.run(function(){
+ require('./util/open').cleanup() || browsers.run(function(){
setTimeout(function(){
location.reload();
}, 15 * 1000);
diff --git a/test/panic/no-override.js b/test/panic/no-override.js
index 8f6d9875..a1e01be5 100644
--- a/test/panic/no-override.js
+++ b/test/panic/no-override.js
@@ -75,7 +75,7 @@ describe("No Empty Object on .Once", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -118,11 +118,7 @@ describe("No Empty Object on .Once", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/on-recovery.js b/test/panic/on-recovery.js
index 9c97a943..4fc6ffe6 100644
--- a/test/panic/on-recovery.js
+++ b/test/panic/on-recovery.js
@@ -72,7 +72,7 @@ describe("gun.on should receive updates after crashed relay peer comes back onli
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -217,7 +217,7 @@ describe("gun.on should receive updates after crashed relay peer comes back onli
});
after("Everything shut down.", function(){
- return bob.run(function(){
+ return require('./util/open').cleanup() || bob.run(function(){
process.exit();
});
});
diff --git a/test/panic/radisk.js b/test/panic/radisk.js
index 3470bf78..cab31467 100644
--- a/test/panic/radisk.js
+++ b/test/panic/radisk.js
@@ -74,7 +74,7 @@ describe("Make sure the Radix Storage Engine (RAD) works.", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -275,11 +275,7 @@ describe("Make sure the Radix Storage Engine (RAD) works.", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/scale.js b/test/panic/scale.js
index ce96e041..33ed3d9d 100644
--- a/test/panic/scale.js
+++ b/test/panic/scale.js
@@ -223,11 +223,7 @@ describe("Stress test GUN with SEA users causing PANIC!", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/set.js b/test/panic/set.js
index 53a8adb4..d72db6b6 100644
--- a/test/panic/set.js
+++ b/test/panic/set.js
@@ -65,7 +65,7 @@ describe("Make sure SEA syncs correctly", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -188,11 +188,7 @@ describe("Make sure SEA syncs correctly", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/speak.js b/test/panic/speak.js
index bea9d3d1..94a7bde5 100644
--- a/test/panic/speak.js
+++ b/test/panic/speak.js
@@ -310,11 +310,7 @@ describe("Stress test GUN with SEA users causing PANIC!", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/thread.js b/test/panic/thread.js
index e8e67d54..01148578 100644
--- a/test/panic/thread.js
+++ b/test/panic/thread.js
@@ -64,7 +64,7 @@ describe("Private Message Threading", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -218,11 +218,7 @@ describe("Private Message Threading", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/users.js b/test/panic/users.js
index 1f77df9e..b08b9bfe 100644
--- a/test/panic/users.js
+++ b/test/panic/users.js
@@ -65,7 +65,7 @@ describe("End-to-End Encryption on User Accounts", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -253,11 +253,7 @@ describe("End-to-End Encryption on User Accounts", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});
diff --git a/test/panic/util/open.js b/test/panic/util/open.js
new file mode 100644
index 00000000..76c87fa0
--- /dev/null
+++ b/test/panic/util/open.js
@@ -0,0 +1,45 @@
+let _browsers = [];
+
+module.exports = {
+ web: (count, url, options) => {
+ if (typeof count === 'string') {
+ options = url;
+ url = count;
+ count = 1;
+ }
+ if (!url || typeof url !== 'string') {
+ throw new Error('Invalid URL');
+ }
+ try {
+ require('puppeteer').launch(options).then(browser => {
+ _browsers.push(browser);
+ Array(count).fill(0).forEach((x, i) => {
+ console.log('Opening browser page ' + i + ' with puppeteer...');
+ browser.newPage().then(page => {
+ page.on('console', msg => {
+ if (msg.text() === 'JSHandle@object') {
+ // FIXME: Avoid text comparison
+ return;
+ }
+ console.log(`${i} [${msg.type()}]: ${msg.text()}`);
+ });
+ return page.goto(url);
+ }).then(() => {
+ console.log('Browser page ' + i + ' open');
+ });
+ });
+ });
+ } catch (err) {
+ console.log("PLEASE OPEN "+ url +" IN "+ count +" BROWSER(S)!");
+ console.warn('Consider installing puppeteer to automate browser management (npm i -g puppeteer && npm link puppeteer)');
+ }
+ },
+ cleanup: () => {
+ if (_browsers.length === 0) {
+ return undefined;
+ }
+ console.log('Closing all puppeteer browsers...');
+ return Promise.all(_browsers.map(b => b.close()))
+ .then(() => console.log('Closed all puppeteer browsers'));
+ }
+}
diff --git a/test/panic/who.js b/test/panic/who.js
index 1deaa5d5..54a0e6f9 100644
--- a/test/panic/who.js
+++ b/test/panic/who.js
@@ -65,7 +65,7 @@ describe("Make sure SEA syncs correctly", function(){
});
it(config.browsers +" browser(s) have joined!", function(){
- console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
+ require('./util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
return browsers.atLeast(config.browsers);
});
@@ -233,11 +233,7 @@ describe("Make sure SEA syncs correctly", function(){
});
after("Everything shut down.", function(){
- browsers.run(function(){
- //location.reload();
- //setTimeout(function(){
- //}, 15 * 1000);
- });
+ require('./util/open').cleanup();
return servers.run(function(){
process.exit();
});