gun/test/panic/axe/data_balance_webrtc.js
Mark Nadal 087704ec6b
Begin 1 Years worth of Merges... (#1116)
* tmp for hn issue

* log top to stats

* test for guntest peer

* try big messages

* parse time?

* what bin/node is 11ms?

* be normal for hnoon

* tolerate 0.5s

* try 3s for hnoon?

* stop empty gets

* tmp for guntest

* back to normal

* check hash time

* back to normal in hear

* screen / upload / play / pause

* merge latest npm release into manhattan

* merge master 0.2020.421 into manhattan manually

* WIP

* manually merge from master

* gatling

* Update upload.html

* work in progress...

* yson panic chat basic

* after `.put(` walk

* restructure acks

* messy but 2 units passing!

* put recursive once on map

* basics

* have NTS use DAM + fix other utils

* Rewrote nts

* Allow passing test cli args.

Before, no CLI args would be passed when running `npm test`. Keeping the `mocha` at the end of the test script allows passing CLI args to Mocha.

* put back scan & once tweak

* PANIC user paste OK

* manhattan sea

* stub out nts for now

* AXE tweak

* tweak for quick first prod testing

* tweak for first in-prod testing

* tweak

* tweak

* sketchy in-prod debug attempt

* caught it? maybe? now restore

* Create download-log.html

* stub out yson test prod?

* ugh, gotta see what is going on

* move dl

* gonna stop doing commit messages for in-prod test/tweaks/debugging

* a

* p

* squelch

* console stats

* stats

* stop travis

* restore yson

* ahhh no file access without sudo

* mem

* no stub

* fix axe

* bump

* back to in-prod testing, isolate/stub out code

* stub all out for 17K ? CPU ? test

* stub dup gc

* ugh main stub

* does this stop url format blocking?

* re-add dup

* no top :(

* will this work?

* get ack stats?

* a map chain may ask for data not a root soul chain

* move proper logic into .get(

* how 2019 compat?

* a couple more!

* more tests passing! :D :)

* even more! SO EXCITING :D

* Am I alive?

* wow I can't believe it works like this

* THANK YOU @rogowski !!!!!!

* Create trace.html

Adding tracing to debuging.

* @rogowski is a super star :) :) :)

* Update trace.js

Change `Gun.logs` to `Gun.traces` and `Gun._log` to `Gun._trace`.

* Update trace.html

Change `Gun.logs` to `Gun.traces` and `Gun._log` to `Gun._trace`.
Overload get,put,on,map

* @rogowski approved of these trace changes :)

* Update trace.html

More decoupled.

* Update trace.js

More decoupled

* 2 steps backwards, 1 step forward?

* back where we ( @rogowski ) started :P

* YAYAYAYAYAYAYAY past where we started at!

* safer to have it here

* slight tweak? Let's see how long it lasts.

* merge checks we left out during consolidation

* ugly common.js for @rogowski

* slightly better

* amazing map discovery + don't clear on not found if data exists

* onto next test...

* all caught up!!! Now update tests from graphify to statedisk

* Update common.js

Tests updated from graphify to statedisk.

* easy to debug & fix thanks to @rogowski 's test upgrades & trace!

* hmm, IDK if we should support this anymore?

* support once chaining?

* check if listener order is earlier than write

* in-process message passing needs to clean itself of flags for now

* ack to chains that can't be reached

* call sub chains on clear/empty WIP

* call sub chains clear/empty OK!

* into unlink. Clean/refactor later.

* oh that was nice

* self check not needed?

* test was poorly constructed?

* refactor unlink to cleaner logic

* Will you blame me for this? Special case, maybe later move to cleaner place?

* use stun's run id instead.

* cleaner unlink logic

* better map, link, and unlink logic.

* unstub relay

* refactor unlink

* invert

* if prev value would have caused unlink, do not unlink again.

* w000h00! Best unlink so far.

* woops, fix unlinking nested

* unsubscribe nested maps (working, tho possible perf regression? check)

* put check soul

* add default uuid

* improved browser peer retry logic, let devices sleep, etc.

* Chaining API unit tests passing!

* merge new panic tests into here to test

* add panic utils

* fix long streaming timeout/expiry issue, update examples

* yield generating test data

* yeah, adapter errors (like out of storage) should not affect sync/networking logic, that was a bad experiment

* git glitch?

* some mid debugging fixes but maybe scary changes, hopefully safe to revert here except dub

* SEA unit tests passing!!! Needed quite a few fixes on async write queue stuff.

* optionally make auth async

* revise/correct set

* Fix reverse boundary check

* Add extra tests, catch bad guy, obliterate bug.

* chat app with emoji examples

* handle empty string keyed objects

* starting lex support

* tweak for lex

* woops! lexical alphabetical oopsies. That was bad.

* upload either way

* debug

* start

* fix

* fix

* clean + feature

* update dependencies in package.json (#1086)

* rad lex once map once

* axe polyfill for now

* oops log

* oops maybe without this it crashed the peer

* what on earth happened to my browser/OS? "unplug & plug it back in" restart seemed to fix it.

* oh, don't memory leak req/res asks. :/ duh!

* no accidental #soul.""

* ugh, still have to sort :(, really should polyfill weakmap then

* oops, pluck needs new object to go into

* oops, make sure soul is passed

* updating deprecated functions

* begin AXE. Next: load balance!

* Update sea.js

* keys are dangerous!

* AXE round robin load balance

* better ash hash checking

* lS reuse in-mem reply chunking

* state machine!!!

* RAD needs to pass cache misses.

* updating deprecated functions (#1088)

* update dependencies in package.json

* updating deprecated functions

* remove where.gundb.io

* Bring SEA.certify into manhattan branch (#1092)

Co-authored-by: Radu Cioienaru <radu@projectmanager.com>

* fix rad, make get() hookable

* rad browser tests seem to be passing!

* reverse user random side, add err, update styles, + more

* fix pack/max, update dom

* paste!

* of course it'll dedup cause it just called track on hear, fix

* 📦 Adding the hub feature to this branch & improvements. (#1102)

* 📦 Adding the hub feature to this branch.

* 🗑 Removed the container for speed improvement !

* 📝 I added some comments to the code.

Co-authored-by: Hector <fairfairytotor@gmail.com>
Co-authored-by: Hector <pro.hector.kub@gmail.com>

* Update axe.js

* 🦅 Wrap everything in a try & catch for error handling…  (#1105)

* 🦅 Wrap everything in a try & catch for error handling & speed improvement.

* 📦 Finally here : opt.file for the hub feature !

* 📦 Finally here : opt.file for the hub feature !

And also : fixed indentation 😋

Co-authored-by: noctisatrae <pro.hector.kub@gmail.com>

* probs better this way, safer

* moved test/axe tests to test/panic/axe.

* New test: axe load balance.

* axe test: webrtc data balance(fix paths and file renamed).

* test axe: renaming webrtc file.

* axe test: separating webrtc test for data_balance.

* axe test: test only with the relay(without webrtc).

* Update sea.js

Same as https://github.com/amark/gun/pull/1062

* Update gun.js

var tmp

* Update upload.js

* merge, update stun

* SEA.certify wire logic + unit tests (#1110)

* SEA.certify wire logic + unit tests

* picking white hair

* ack err

* axe tests using puppeteer.

* change stun system

* ~20lines

* put use parent soul link if need

* handle errors

* finally seems fixed

* cb not to

* relay

* nasty bug! Don't crash, tho need to find what causes it

* undo local changes/notes to self

* deprecation warnings

* "old" data to test against

* oops, forgot I played with ascii

* debug

* in-prod check: sites

* in-prod isolate

* gotta find this, by stubbing out

* where?

* will this work?

* clearly not, lol what's the point then? maybe like this

* and again

* must we?

* USE THIS MANHATTAN VERSION

* clean

* better panic hints

Co-authored-by: Robin Bron <finwo@pm.me>
Co-authored-by: Pavel Diatchenko <diatche@users.noreply.github.com>
Co-authored-by: rogowski <163828+rogowski@users.noreply.github.com>
Co-authored-by: I001962 <i001962@gmail.com>
Co-authored-by: Adriano Rogowski <rogowski.adriano@gmail.com>
Co-authored-by: Radu <cetatuie@gmail.com>
Co-authored-by: Radu Cioienaru <radu@projectmanager.com>
Co-authored-by: Hector <46224745+noctisatrae@users.noreply.github.com>
Co-authored-by: Hector <fairfairytotor@gmail.com>
Co-authored-by: Hector <pro.hector.kub@gmail.com>
Co-authored-by: Martti Malmi <sirius@iki.fi>
Co-authored-by: mimiza <dev@mimiza.com>
2021-08-21 21:19:29 -07:00

420 lines
12 KiB
JavaScript

/**
* AXE test data balance webrtc
* What we want here: (1) Superpeer and (n) peers
* - The peers receives only the requested data.
* - If the Superpeer crash, after restart, must recreate all subscriptions and update the peers.
* - If some peer crash or go offline, must receive the changes via RTC.
*/
var config = {
IP: require('ip').address(),
port: 8765,
servers: 2,
browsers: 3,
route: {
'/': __dirname + '/index.html',
'/gun.js': __dirname + '/../../../gun.js',
'/gun/axe.js': __dirname + '/../../../axe.js',
'/gun/lib/webrtc.js': __dirname + '/../../../lib/webrtc.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 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);
var again = {};
describe("The Holy Grail AXE Test!", function(){
this.timeout(5 * 60 * 1000);
// this.timeout(10 * 60 * 1000);
it("Servers have joined!", function(){
return servers.atLeast(config.servers);
});
it("GUN started!", function(){
return server.run(function(test){
var env = test.props;
test.async();
try{ require('fs').unlinkSync(env.i+'dataaxe') }catch(e){}
try{ require('fs').unlinkSync((env.i+1)+'dataaxe') }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 = require('gun');
require('gun/axe');
var gun = Gun({
file: env.i+'dataaxe',
web: server
});
server.listen(port, function(){
test.done();
});
}, {i: 1, config: config});
});
it(config.browsers +" browser(s) have joined!", function(){
require('../util/open').web(config.browsers, "http://"+ config.IP +":"+ config.port);
// 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){
localStorage.clear(); console.log('Clear localStorage!!!');
var env = test.props;
var opt = {peers:['http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun'], wait: 1000};
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.getElementById('pid').innerHTML = (document.getElementById('pid').innerHTML || "-") + ', ' + this.on.opt.pid;
});
});
var gun = window.gun = Gun(opt);
window.ref = gun.get('holy').get('grail');
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});
it("Wait for Alice, Bob and John...", function(done){
setTimeout(done, 1000);
});
it("Alice Write: Hi Bob!", function(){
return alice.run(function(test){
console.log("I AM ALICE");
$('#name').text('Alice');
test.async();
ref.once(function() { // TODO: Need `.once` first for subscription. If Alice do a `.put` before a `.once`, Alice will get old data from localStorage if Bob update
ref.put('Hi Bob!', function(ack) {
console.log(ack);
setTimeout(test.done, 2000);
});
});
});
});
it("Bob receive ONCE from Alice: Hi Bob!", function(){
return bob.run(function(test){
console.log("I AM BOB");
$('#name').text('Bob');
test.async();
ref.once(function(data){
if('Hi Bob!' === data){
console.log('[OK] Bob receive the question: ', data);
return test.done();
} else {
var err = '[FAIL] Bob MUST receive: Hi Bob! but receive: ' + data + ' Storage: ' + localStorage.getItem('gun/');
console.log(err);
return test.fail(err);
}
})
})
});
it("Bob Write response: Hi Alice!", function(){
return bob.run(function(test){
test.async();
ref.put('Hi Alice!', function(ack) {
console.log('[OK] Bob Write response: Hi Alice!', ack);
setTimeout(test.done, 2000);
});
});
});
it("Alice Read response from Bob: Hi Alice!", function(){
return alice.run(function(test){
test.async();
ref.once(function(data){
if('Hi Alice!' === data){
console.log('[OK] Alice receive the response: ', data);
return test.done();
} else {
//TODO: aqui em duvida.. está pegando do localStorage, mas Bob alterou o dado.
var err = '[FAIL] Alice receive wrong response: "' + data + '" and must be "Hi Alice!"';
console.log(err);
return test.fail(err);
}
})
})
});
it("John Read what Bob say to Alice: Hi Alice!", function(){
return john.run(function(test){
test.async();
console.log("I AM JOHN");
$('#name').text('John');
ref.once(function(data){
if('Hi Alice!' === data){
console.log('[OK] John receive the data: ', data);
return test.done();
} else {
//TODO: aqui em duvida.. está pegando do localStorage, mas Bob alterou o dado.
var err = '[FAIL] John receive wrong data: "' + data + '" and must be "Hi Alice!"';
console.log(err);
return test.fail(err);
}
})
})
});
it("Bob Write in some data, Alice not subscribed", function(){
return bob.run(function(test){
test.async();
gun.get('bob').get('mine').put('Alice dont want this data now!', function() {
setTimeout(test.done, 2000);
});
});
});
it("Alice not subscribed. Must NOT receive data from Bob", function(){
return alice.run(function(test){
test.async();
/// This must be empty, because alice don't make a subscription to this node.
var bobdata = JSON.parse(localStorage.getItem('gun/')).bob;
if (bobdata) {
var err = '[FAIL] Alice receive not subscribed data in localStorage: ' + JSON.stringify(bobdata);
console.log(err);
return test.fail(err);
}
if (gun._.graph.bob) {
var err = '[FAIL] Alice receive not subscribed data in in graph: ' + JSON.stringify(gun._.graph.bob);
console.log(err);
return test.fail(err);
}
console.log('[OK] Alice Read must NOT receive data from Bob: ', bobdata);
return test.done();
})
});
it("Alice subscription Bob data with ONCE, MUST receive", function(){
return alice.run(function(test){
test.async();
gun.get('bob').once(function(data){
if(data){
console.log('[OK] Alice receive the value: ', data);
return test.done();
} else {
var err = '[FAIL] Alice receive the value: ' + data;
console.log(err);
return test.fail(err);
}
})
})
});
it("Bob Write in some data. Now Alice is subscribed.", function(){
return bob.run(function(test){
test.async();
gun.get('bob').get('mine').put('Alice WANT this data now!', function() {
setTimeout(test.done, 5000);
});
});
});
it("Alice must receive 'Alice WANT this data now!' from Bob node", function(){
return alice.run(function(test){
test.async();
if (gun._.graph.bob && gun._.graph.bob.mine === 'Alice WANT this data now!') {
console.log('[OK] GRAPH: ', gun._.graph.bob);
test.done();
} else {
var err = '[FAIL] GRAPH: ' + JSON.stringify(gun._.graph.bob);
console.log(err);
test.fail(err);
}
})
});
it("Server has crashed!", function(){
return server.run(function(test){
// var env = test.props;
// try{ require('fs').unlinkSync(env.i+'data'); }catch(e){}
process.exit(0);
}, {i: 1, config: config})
});
it("Wait...", function(done){
setTimeout(done, 2000);
});
it("Alice change the data (superpeer crashed yet).", function(){
return alice.run(function(test){
var env = test.props;
if(window.WebSocket){
var err;
try{ new WebSocket('http://'+ env.config.IP + ':' + (env.config.port + 2) + '/gun') }catch(e){ err = e }
if(!err){
test.fail("Server did not crash.");
}
}
test.async()
ref.put("Superpeer? Where are you?", function() {
setTimeout(test.done, 1000);
});
}, {config: config});
});
it("Bob receive what Alice change via WebRTC.", function(){
return bob.run(function(test){
test.async();
ref.once(function(data){
if('Superpeer? Where are you?' === data){
console.log('[OK] Bob received data via WebRTC: ', data);
return test.done();
} else {
var err = '[FAIL] Bob MUST not receive: "Superpeer? Where are you?", but receive: ' + data;
console.log(err);
return test.fail(err);
}
})
})
});
it("Bob change the data again (superpeer crashed yet).", function(){
return alice.run(function(test){
var env = test.props;
if(window.WebSocket){
var err;
try{ new WebSocket('http://'+ env.config.IP + ':' + (env.config.port + 2) + '/gun') }catch(e){ err = e }
if(!err){
test.fail("Server did not crash.");
}
}
test.async()
ref.put("Alice, can you hear me?", function() {
setTimeout(test.done, 1000);
});
}, {config: config});
});
it("Alice MUST receive 'Alice, can you hear me?' via WebRTC.", function(){
return bob.run(function(test){
test.async();
ref.once(function(data){
if('Alice, can you hear me?' === data){
console.log('[OK] Alice received data via WebRTC: ', data);
return test.done();
} else {
var err = '[FAIL] Alice MUST not receive: "Superpeer? Where are you?", but receive: ' + data;
console.log(err);
return test.fail(err);
}
})
})
});
it("Superpeer come started again!", function(){
return server2.run(function(test){
var env = test.props;
test.async();
// try{ require('fs').unlinkSync(env.i+'dataaxe') }catch(e){}
// try{ require('fs').unlinkSync((env.i+1)+'dataaxe') }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 = require('gun');
require('gun/axe');
var gun = Gun({
file: env.i+'dataaxe',
web: server
});
server.listen(port, function(){
test.done();
});
}, {i: 1, config: config});
});
it("Wait sync...", function(done){
setTimeout(done, 5000);
});
it("Alice change the data again (superpeer is UP!).", function(){
return alice.run(function(test){
var env = test.props;
test.async()
ref.put("Yes Bob! Thanks for asking!", function() {
setTimeout(test.done, 1000);
});
}, {config: config});
});
it("Bob MUST receive 'Yes Bob! Thanks for asking!'", function(){
return bob.run(function(test){
test.async();
ref.once(function(data){
if('Yes Bob! Thanks for asking!' === data){
console.log('[OK] Bob received the data change: ', data);
return test.done();
} else {
var err = '[FAIL] Bob MUST not receive: "Yes Bob! Thanks for asking!", but receive: ' + data;
console.log(err);
return test.fail(err);
}
})
})
});
it("John dont want to know what Bob say in his node!", function(){
return john.run(function(test){
test.async();
/// This must be empty, because John don't make a subscription to this node.
var bobdata = JSON.parse(localStorage.getItem('gun/')).bob;
if (bobdata) {
var err = '[FAIL] John receive not subscribed data: ' + JSON.stringify(bobdata);
console.log(err);
return test.fail(err);
}
if (gun._.graph.bob) {
var err = '[FAIL] John receive not subscribed data in in graph: ' + JSON.stringify(gun._.graph.bob);
console.log(err);
return test.fail(err);
}
console.log('[OK] John Read must NOT receive data from Bob: ', bobdata, gun._.graph.bob);
return test.done();
})
});
it("All finished!", function(done){
console.log("Done! Cleaning things up...");
setTimeout(function(){
done();
},1000);
});
after("Everything shut down.", function(){
require('../util/open').cleanup() || browsers.run(function(){
setTimeout(location.reload, 15 * 1000);
});
return servers.run(function(){
process.exit();
});
});
});