gun/test/common.js
2016-01-25 20:22:32 -08:00

3834 lines
115 KiB
JavaScript

(function(env){
root = env.window? env.window : root;
env.window && root.localStorage && root.localStorage.clear();
//root.Gun = root.Gun || require('../gun');
root.Gun = root.Gun || require('../gun');
}(this));
//Gun.log.squelch = true;
var gleak = {globals: {}, check: function(){ // via tobyho
var leaked = []
for (var key in gleak.globe){ if (!(key in gleak.globals)){ leaked.push(key)} }
if (leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked }
}};
(function(env){
for (var key in (gleak.globe = env)){ gleak.globals[key] = true }
}(this));
describe('Performance', function(){ return; // performance tests
var console = root.console || {log: function(){}};
function perf(fn, i){
i = i || 1000;
while(--i){
fn(i);
}
}
perf.now = this.performance? function(){ return performance.now() } : function(){ return Gun.time.now()/1000 };
(function(){
var t1 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
Object.keys && perf(function(){
var l = Object.keys(obj), ll = l.length, i = 0, s = '';
for(; i < ll; i++){
var v = l[i];
s += v;
}
});
console.log('map: native', (t1 = (perf.now() - t1)/1000) + 's');
var t2 = perf.now();
var obj = {1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i'};
perf(function(){
var s = '';
Gun.obj.map(obj, function(v){
s += v;
})
});
console.log('map: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());
(function(){
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var it = 1000;
var t1 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}, it);
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){ // setTimeout
if(!Gun.store){
var tab = Gun().tab;
if(!tab){ return }
Gun.store = tab.store;
}
root.localStorage && root.localStorage.clear();
var t1 = perf.now();
i = i || 1000;
while(--i){
var obj = {'i': i, 'v': Gun.text.random(100)};
Gun.store.put('test/native/' + i, obj);
}
console.log('store: native', (t1 = (perf.now() - t1)/1000) + 's');
root.localStorage && root.localStorage.clear();
var gun = Gun({wire: {get:function(l,cb){cb()},put:function(g,cb){
Gun.is.graph(g, function(node, soul){
Gun.store.put(soul, node);
});
cb(null);
}}});
var t2 = perf.now();
perf(function(i){
var obj = {'i': i, 'v': Gun.text.random(100)};
gun.put(obj);
}, it);
console.log('store: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
root.localStorage && root.localStorage.clear();
}());
(function(){
var t1 = perf.now();
var on = Gun.on.create(), c = 0, o = [];
perf(function(i){
o.push(function(n){
c += 1;
});
var ii = 0, l = o.length;
for(; ii < l; ii++){
o[ii](i);
}
});
console.log('on: native', (t1 = (perf.now() - t1)/1000) + 's');
var on = Gun.on.create(), c = 0;
var t2 = perf.now();
perf(function(i){
on('change').event(function(n){
c += 1;
});
on('change').emit(i);
});
console.log('on: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}());return;
(function(){ // always do this last!
var t1 = perf.now();
perf(function(i){
setTimeout(function(){
if(i === 1){
cb1();
}
},0);
}); var cb1 = function(){
console.log('setTimeout: native', (t1 = (perf.now() - t1)/1000) + 's', (t1 / t2).toFixed(1)+'x', 'slower.');
}
var t2 = perf.now();
perf(function(i){
setImmediate(function(){
if(i === 1){
cb2();
}
});
}); var cb2 = function(){
console.log('setImmediate: gun', (t2 = (perf.now() - t2)/1000) + 's', (t2 / t1).toFixed(1)+'x', 'slower.');
}
}());
});
describe('Gun', function(){
var t = {};
describe('Utility', function(){
var u;
/* // causes logger to no longer log.
it('verbose console.log debugging', function(done) {
var gun = Gun();
var log = root.console.log, counter = 1;
root.console.log = function(a,b,c){
--counter;
//log(a,b,c);
}
Gun.log.verbose = true;
gun.put('bar', function(err, yay){ // intentionally trigger an error that will get logged.
expect(counter).to.be(0);
Gun.log.verbose = false;
gun.put('bar', function(err, yay){ // intentionally trigger an error that will get logged.
expect(counter).to.be(0);
root.console.log = log;
done();
});
});
} );
*/
describe('Type Check', function(){
it('binary', function(){
expect(Gun.bi.is(false)).to.be(true);
expect(Gun.bi.is(true)).to.be(true);
expect(Gun.bi.is(u)).to.be(false);
expect(Gun.bi.is(null)).to.be(false);
expect(Gun.bi.is('')).to.be(false);
expect(Gun.bi.is('a')).to.be(false);
expect(Gun.bi.is(0)).to.be(false);
expect(Gun.bi.is(1)).to.be(false);
expect(Gun.bi.is([])).to.be(false);
expect(Gun.bi.is([1])).to.be(false);
expect(Gun.bi.is({})).to.be(false);
expect(Gun.bi.is({a:1})).to.be(false);
expect(Gun.bi.is(function(){})).to.be(false);
});
it('number',function(){
expect(Gun.num.is(0)).to.be(true);
expect(Gun.num.is(1)).to.be(true);
expect(Gun.num.is(Infinity)).to.be(true);
expect(Gun.num.is(u)).to.be(false);
expect(Gun.num.is(null)).to.be(false);
expect(Gun.num.is(NaN)).to.be(false);
expect(Gun.num.is('')).to.be(false);
expect(Gun.num.is('a')).to.be(false);
expect(Gun.num.is([])).to.be(false);
expect(Gun.num.is([1])).to.be(false);
expect(Gun.num.is({})).to.be(false);
expect(Gun.num.is({a:1})).to.be(false);
expect(Gun.num.is(false)).to.be(false);
expect(Gun.num.is(true)).to.be(false);
expect(Gun.num.is(function(){})).to.be(false);
});
it('text',function(){
expect(Gun.text.is('')).to.be(true);
expect(Gun.text.is('a')).to.be(true);
expect(Gun.text.is(u)).to.be(false);
expect(Gun.text.is(null)).to.be(false);
expect(Gun.text.is(false)).to.be(false);
expect(Gun.text.is(true)).to.be(false);
expect(Gun.text.is(0)).to.be(false);
expect(Gun.text.is(1)).to.be(false);
expect(Gun.text.is([])).to.be(false);
expect(Gun.text.is([1])).to.be(false);
expect(Gun.text.is({})).to.be(false);
expect(Gun.text.is({a:1})).to.be(false);
expect(Gun.text.is(function(){})).to.be(false);
});
it('list',function(){
expect(Gun.list.is([])).to.be(true);
expect(Gun.list.is([1])).to.be(true);
expect(Gun.list.is(u)).to.be(false);
expect(Gun.list.is(null)).to.be(false);
expect(Gun.list.is(0)).to.be(false);
expect(Gun.list.is(1)).to.be(false);
expect(Gun.list.is('')).to.be(false);
expect(Gun.list.is('a')).to.be(false);
expect(Gun.list.is({})).to.be(false);
expect(Gun.list.is({a:1})).to.be(false);
expect(Gun.list.is(false)).to.be(false);
expect(Gun.list.is(true)).to.be(false);
expect(Gun.list.is(function(){})).to.be(false);
});
it('obj',function(){
expect(Gun.obj.is({})).to.be(true);
expect(Gun.obj.is({a:1})).to.be(true);
expect(Gun.obj.is(u)).to.be(false);
expect(Gun.obj.is()).to.be(false);
expect(Gun.obj.is(undefined)).to.be(false);
expect(Gun.obj.is(null)).to.be(false);
expect(Gun.obj.is(NaN)).to.be(false);
expect(Gun.obj.is(0)).to.be(false);
expect(Gun.obj.is(1)).to.be(false);
expect(Gun.obj.is('')).to.be(false);
expect(Gun.obj.is('a')).to.be(false);
expect(Gun.obj.is([])).to.be(false);
expect(Gun.obj.is([1])).to.be(false);
expect(Gun.obj.is(false)).to.be(false);
expect(Gun.obj.is(true)).to.be(false);
expect(Gun.obj.is(function(){})).to.be(false);
expect(Gun.obj.is(new Date())).to.be(false);
expect(Gun.obj.is(/regex/)).to.be(false);
this.document && expect(Gun.obj.is(document.createElement('div'))).to.be(false);
expect(Gun.obj.is(new (function Class(){ this.x = 1; this.y = 2 })())).to.be(true);
});
it('fns',function(){
expect(Gun.fns.is(function(){})).to.be(true);
expect(Gun.fns.is(u)).to.be(false);
expect(Gun.fns.is(null)).to.be(false);
expect(Gun.fns.is('')).to.be(false);
expect(Gun.fns.is('a')).to.be(false);
expect(Gun.fns.is(0)).to.be(false);
expect(Gun.fns.is(1)).to.be(false);
expect(Gun.fns.is([])).to.be(false);
expect(Gun.fns.is([1])).to.be(false);
expect(Gun.fns.is({})).to.be(false);
expect(Gun.fns.is({a:1})).to.be(false);
expect(Gun.fns.is(false)).to.be(false);
expect(Gun.fns.is(true)).to.be(false);
});
it('time',function(){
t.ts = Gun.time.is();
expect(13 <= t.ts.toString().length).to.be.ok();
expect(Gun.num.is(t.ts)).to.be.ok();
expect(Gun.time.is(new Date())).to.be.ok();
});
});
describe('Text', function(){
it('ify',function(){
expect(Gun.text.ify(0)).to.be('0');
expect(Gun.text.ify(22)).to.be('22');
expect(Gun.text.ify([true,33,'yay'])).to.be('[true,33,"yay"]');
expect(Gun.text.ify({a:0,b:'1',c:[0,'1'],d:{e:'f'}})).to.be('{"a":0,"b":"1","c":[0,"1"],"d":{"e":"f"}}');
expect(Gun.text.ify(false)).to.be('false');
expect(Gun.text.ify(true)).to.be('true');
});
it('random',function(){
expect(Gun.text.random().length).to.be(24);
expect(Gun.text.random(11).length).to.be(11);
expect(Gun.text.random(4).length).to.be(4);
t.tr = Gun.text.random(2,'as'); expect((t.tr=='as'||t.tr=='aa'||t.tr=='sa'||t.tr=='ss')).to.be.ok();
});
it('match',function(){
expect(Gun.text.match("user/mark", {'=': 'user/mark'})).to.be.ok();
expect(Gun.text.match("user/mark/nadal", {'=': 'user/mark'})).to.not.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/'})).to.be.ok();
expect(Gun.text.match("email/mark@gunDB.io", {'*': 'user/'})).to.not.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '>': 'j', '<': 'o'})).to.be.ok();
expect(Gun.text.match("user/amber/nadal", {'*': 'user/', '>': 'j', '<': 'o'})).to.not.be.ok();
expect(Gun.text.match("user/amber/nadal", {'*': 'user/', '>': 'a', '<': 'c'})).to.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '>': 'a', '<': 'c'})).to.not.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '>': 'j', '<': 'o', '?': 'm/n'})).to.be.ok();
expect(Gun.text.match("user/amber/cazzell", {'*': 'user/', '?': 'm/n'})).to.not.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '-': 'mad'})).to.be.ok();
expect(Gun.text.match("user/mad/person", {'*': 'user/', '-': 'mad'})).to.not.be.ok();
expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '+': 'ark'})).to.be.ok();
expect(Gun.text.match("user/mad/person", {'*': 'user/', '+': 'ark'})).to.not.be.ok();
expect(Gun.text.match("photo/kitten.jpg", {'*': 'photo/', '&': '.jpg'})).to.be.ok();
expect(Gun.text.match("photo/kittens.gif", {'*': 'photo/', '&': '.jpg'})).to.not.be.ok();
});
});
describe('List', function(){
it('slit',function(){
(function(){
expect(Gun.list.slit.call(arguments, 0)).to.eql([1,2,3,'a','b','c']);
}(1,2,3,'a','b','c'));
});
it('sort',function(){
expect([{i:9},{i:4},{i:1},{i:-3},{i:0}].sort(Gun.list.sort('i'))).to.eql([{i:-3},{i:0},{i:1},{i:4},{i:9}]);
});
it('map',function(){
expect(Gun.list.map([1,2,3,4,5],function(v,i,t){ t(v+=this.d); this.d=v; },{d:0})).to.eql([1,3,6,10,15]);
expect(Gun.list.map([2,3,0,4],function(v,i,t){ if(!v){ return } t(v*=this.d); this.d=v; },{d:1})).to.eql([2,6,24]);
expect(Gun.list.map([true,false,NaN,Infinity,'',9],function(v,i,t){ if(i===3){ return 0 }})).to.be(0);
});
});
describe('Object', function(){
it('del',function(){
var obj = {a:1,b:2};
Gun.obj.del(obj,'a');
expect(obj).to.eql({b:2});
});
it('has',function(){
var obj = {a:1,b:2};
expect(Gun.obj.has(obj,'a')).to.be.ok();
});
it('empty',function(){
expect(Gun.obj.empty()).to.be(true);
expect(Gun.obj.empty({a:false})).to.be(false);
expect(Gun.obj.empty({a:false},'a')).to.be(true);
expect(Gun.obj.empty({a:false},{a:1})).to.be(true);
expect(Gun.obj.empty({a:false,b:1},'a')).to.be(false);
expect(Gun.obj.empty({a:false,b:1},{a:1})).to.be(false);
expect(Gun.obj.empty({1:1},'danger')).to.be(false);
});
it('copy',function(){
var obj = {"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}};
var copy = Gun.obj.copy(obj);
expect(copy).to.eql(obj);
expect(copy).to.not.be(obj);
});
it('ify',function(){
expect(Gun.obj.ify('[0,1]')).to.eql([0,1]);
expect(Gun.obj.ify('{"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}')).to.eql({"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}});
});
it('map',function(){
expect(Gun.obj.map({a:'z',b:'y',c:'x'},function(v,i,t){ t(v,i) })).to.eql({x:'c',y:'b',z:'a'});
expect(Gun.obj.map({a:'z',b:false,c:'x'},function(v,i,t){ if(!v){ return } t(i,v) })).to.eql({a:'z',c:'x'});
expect(Gun.obj.map({a:'z',b:3,c:'x'},function(v,i,t){ if(v===3){ return 0 }})).to.be(0);
});
});
describe('Functions', function(){
/*
it.skip('sum',function(done){ // deprecate?
var obj = {a:2, b:2, c:3, d: 9};
Gun.obj.map(obj, function(num, key){
setTimeout(this.add(function(){
this.done(null, num * num);
}, key), parseInt((""+Math.random()).substring(2,5)));
}, Gun.fns.sum(function(err, val){
expect(val.a).to.eql(4);
expect(val.b).to.eql(4);
expect(val.c).to.eql(9);
expect(val.d).to.eql(81);
done();
}));
});
*/
});
describe('Gun Safety', function(){
var gun = Gun();
it('is',function(){
expect(Gun.is(gun)).to.be(true);
expect(Gun.is(true)).to.be(false);
expect(Gun.is(false)).to.be(false);
expect(Gun.is(0)).to.be(false);
expect(Gun.is(1)).to.be(false);
expect(Gun.is('')).to.be(false);
expect(Gun.is('a')).to.be(false);
expect(Gun.is(Infinity)).to.be(false);
expect(Gun.is(NaN)).to.be(false);
expect(Gun.is([])).to.be(false);
expect(Gun.is([1])).to.be(false);
expect(Gun.is({})).to.be(false);
expect(Gun.is({a:1})).to.be(false);
expect(Gun.is(function(){})).to.be(false);
});
it('is value',function(){
expect(Gun.is.val(false)).to.be(true);
expect(Gun.is.val(true)).to.be(true);
expect(Gun.is.val(0)).to.be(true);
expect(Gun.is.val(1)).to.be(true);
expect(Gun.is.val('')).to.be(true);
expect(Gun.is.val('a')).to.be(true);
expect(Gun.is.val({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.is.val({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.is.val(Infinity)).to.be(false); // boohoo :(
expect(Gun.is.val(NaN)).to.be(false);
expect(Gun.is.val([])).to.be(false);
expect(Gun.is.val([1])).to.be(false);
expect(Gun.is.val({})).to.be(false);
expect(Gun.is.val({a:1})).to.be(false);
expect(Gun.is.val(function(){})).to.be(false);
});
it('is soul',function(){
expect(Gun.is.rel({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.is.rel({'#':'somethingelsehere'})).to.be('somethingelsehere');
expect(Gun.is.rel({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.is.rel({or: 'nope', '#':'somesoulidhere'})).to.be(false);
expect(Gun.is.rel(false)).to.be(false);
expect(Gun.is.rel(true)).to.be(false);
expect(Gun.is.rel('')).to.be(false);
expect(Gun.is.rel('a')).to.be(false);
expect(Gun.is.rel(0)).to.be(false);
expect(Gun.is.rel(1)).to.be(false);
expect(Gun.is.rel(Infinity)).to.be(false); // boohoo :(
expect(Gun.is.rel(NaN)).to.be(false);
expect(Gun.is.rel([])).to.be(false);
expect(Gun.is.rel([1])).to.be(false);
expect(Gun.is.rel({})).to.be(false);
expect(Gun.is.rel({a:1})).to.be(false);
expect(Gun.is.rel(function(){})).to.be(false);
});
it('is node',function(){
expect(Gun.is.node({_:{'#':'somesoulidhere'}})).to.be(true);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(true);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({})).to.be(false);
expect(Gun.is.node({a:1})).to.be(false);
expect(Gun.is.node({_:{}})).to.be(false);
expect(Gun.is.node({_:{}, a:1})).to.be(false);
expect(Gun.is.node({'#':'somesoulidhere'})).to.be(false);
});
it('is graph',function(){
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: 1, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{'#':'FOO'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({})).to.be(false); // Empty graph is not a graph :(
expect(Gun.is.graph({a:1})).to.be(false);
expect(Gun.is.graph({_:{}})).to.be(false);
expect(Gun.is.graph({_:{}, a:1})).to.be(false);
expect(Gun.is.graph({'#':'somesoulidhere'})).to.be(false);
});
});
});
describe('ify', function(){
var test, gun = Gun();
it('null', function(done){
Gun.ify(null)(function(err, ctx){
expect(err).to.be.ok();
done();
});
});
it('basic', function(done){
var data = {a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null};
Gun.ify(data, null, {pure: true})(function(err, ctx){
expect(err).to.not.be.ok();
expect(ctx.err).to.not.be.ok();
expect(ctx.root).to.eql(data);
expect(ctx.root === data).to.not.ok();
done();
});
});
it('basic soul', function(done){
var data = {_: {'#': 'SOUL'}, a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null};
Gun.ify(data, null, {pure: true})(function(err, ctx){
expect(err).to.not.be.ok();
expect(ctx.err).to.not.be.ok();
expect(ctx.root).to.eql(data);
expect(ctx.root === data).to.not.be.ok();
expect(Gun.is.node.soul(ctx.root) === Gun.is.node.soul(data));
done();
});
});
it('arrays', function(done){
var data = {before: {path: 'kill'}, one: {two: {lol: 'troll', three: [9, 8, 7, 6, 5]}}};
Gun.ify(data)(function(err, ctx){
expect(err).to.be.ok();
expect(err.err.indexOf("one.two.three")).to.not.be(-1);
done();
});
});
it('undefined', function(done){
var data = {z: undefined, x: 'bye'};
Gun.ify(data)(function(err, ctx){
expect(err).to.be.ok();
done();
});
});
it('NaN', function(done){
var data = {a: NaN, b: 2};
Gun.ify(data)(function(err, ctx){
expect(err).to.be.ok();
done();
});
});
it('Infinity', function(done){ // SAD DAY PANDA BEAR :( :( :(... Mark wants Infinity. JSON won't allow.
var data = {a: 1, b: Infinity};
Gun.ify(data)(function(err, ctx){
expect(err).to.be.ok();
done();
});
});
it('function', function(done){
var data = {c: function(){}, d: 'hi'};
Gun.ify(data)(function(err, ctx){
expect(err).to.be.ok();
done();
});
});
it('extraneous', function(done){
var data = {_: {'#': 'shhh', meta: {yay: 1}}, sneak: true};
Gun.ify(data)(function(err, ctx){
expect(err).to.not.be.ok(); // extraneous metadata needs to be stored, but it can't be used for data.
done();
});
});
return; // TODO! Fix GUN to handle this!
data = {};
data.sneak = false;
data.both = {inside: 'meta data'};
data._ = {'#': 'shhh', data: {yay: 1}, spin: data.both};
test = Gun.ify(data);
expect(test.err.meta).to.be.ok(); // TODO: Fail: this passes, somehow? Fix ify code!
});
describe('Event Promise Back In Time', function(){ return; // TODO: I think this can be removed entirely now.
/*
var ref = gun.put({field: 'value'}).key('field/value').get('field/value', function(){
expect()
});
setTimeout(function(){
ref.get('field/value', function(){
expect();
});
}, 50);
A) Synchronous
1. fake (B)
B) Asychronous
1. In Memory
DONE
2. Will be in Memory
LISTEN to something SO WE CAN RESUME
DONE
3. Not in Memory
Ask others.
DONE
*/
it('A1', function(done){ // this has behavior of a .get(key) where we already have it in memory but need to fake async it.
var graph = {};
var keys = {};
graph['soul'] = {foo: 'bar'};
keys['some/key'] = graph['soul'];
var ctx = {key: 'some/key'};
if(ctx.node = keys[ctx.key]){
console.log("yay we are synchronously in memory!");
setTimeout(function(){
expect(ctx.flag).to.be.ok();
expect(ctx.node.foo).to.be('bar');
done();
},0);
ctx.flag = true;
}
});
it('B1', function(done){ // this has the behavior a .val() where we don't even know what is going on, we just want context.
var graph = {};
var keys = {};
var ctx = {
promise: function(cb){
setTimeout(function(){
graph['soul'] = {foo: 'bar'};
keys['some/key'] = graph['soul'];
cb('soul');
},50);
}
};
if(ctx.node = keys[ctx.key]){
// see A1 test
} else {
ctx.promise(function(soul){
if(ctx.node = graph[soul]){
expect(ctx.node.foo).to.be('bar');
done();
} else {
// I don't know
}
});
}
});
it('B2', function(done){ // this is the behavior of a .get(key) which synchronously follows a .put(obj).key(key) which fakes async.
var graph = {};
var keys = {};
var ctx = {};
(function(data){ // put
setTimeout(function(){
graph['soul'] = data;
fn();
},10);
ctx.promise = function(fn){
}
}({field: "value"}));
(function(key){ // key
keys[key] = true;
ctx.promise(function(){
keys[key] = node;
})
}('some/key'));
(function(ctx){ // get
if(get.node = keys[get.key]){
} else
if(get.inbetweenMemory){
} else {
loadFromDiskOrPeers(get.key, function(){
});
}
}({key: 'some/key'}));
});
});
describe('Schedule', function(){
it('one', function(done){
Gun.schedule(Gun.time.is(), function(){
expect(true).to.be(true);
done(); //setTimeout(function(){ done() },1);
});
});
it('many', function(done){
Gun.schedule(Gun.time.is() + 50, function(){
done.first = true;
});
Gun.schedule(Gun.time.is() + 100, function(){
done.second = true;
});
Gun.schedule(Gun.time.is() + 200, function(){
done.third = true;
expect(done.first).to.be(true);
expect(done.second).to.be(true);
expect(done.third).to.be(true);
done(); //setTimeout(function(){ done() },1);
});
});
});
describe('Union', function(){
var gun = Gun();
it('fail', function(){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
a: 'cheating'
}},
a: 0
}
}
expect(gun.__.graph['asdf']).to.not.be.ok();
var ctx = Gun.union(gun, prime);
expect(ctx.err).to.be.ok();
});
it('basic', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
a: Gun.time.is()
}},
a: 0
}
}
expect(gun.__.graph['asdf']).to.not.be.ok();
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['asdf'].a).to.be(0);
done();
});
});
it('disjoint', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
b: Gun.time.is()
}},
b: 'c'
}
}
expect(gun.__.graph['asdf'].a).to.be(0);
expect(gun.__.graph['asdf'].b).to.not.be.ok();
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['asdf'].a).to.be(0);
expect(gun.__.graph['asdf'].b).to.be('c');
done();
});
});
it('mutate', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
b: Gun.time.is()
}},
b: 'd'
}
}
expect(gun.__.graph['asdf'].b).to.be('c');
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['asdf'].b).to.be('d');
done();
});
});
it('disjoint past', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
x: 0 // beginning of time!
}},
x: 'hi'
}
}
expect(gun.__.graph['asdf'].x).to.not.be.ok();
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['asdf'].x).to.be('hi');
done();
});
});
it('past', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
x: Gun.time.is() - (60 * 1000) // above lower boundary, below now or upper boundary.
}},
x: 'hello'
}
}
expect(gun.__.graph['asdf'].x).to.be('hi');
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['asdf'].x).to.be('hello');
done();
});
});
it('future', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
x: Gun.time.is() + (200) // above now or upper boundary, aka future.
}},
x: 'how are you?'
}
}
expect(gun.__.graph['asdf'].x).to.be('hello');
var now = Gun.time.is();
var ctx = Gun.union(gun, prime, function(){
expect(Gun.time.is() - now).to.be.above(100);
expect(gun.__.graph['asdf'].x).to.be('how are you?');
done();
});
});
var to = 5000;
it('disjoint future', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
y: Gun.time.is() + (200) // above now or upper boundary, aka future.
}},
y: 'goodbye'
}
}
expect(gun.__.graph['asdf'].y).to.not.be.ok();
var now = Gun.time.is();
var ctx = Gun.union(gun, prime, function(){
expect(Gun.time.is() - now).to.be.above(100);
expect(gun.__.graph['asdf'].y).to.be('goodbye');
done();
});
});
it('disjoint future max', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
y: Gun.time.is() + (2), // above now or upper boundary, aka future.
z: Gun.time.is() + (200) // above now or upper boundary, aka future.
}},
y: 'bye',
z: 'who'
}
}
expect(gun.__.graph['asdf'].y).to.be('goodbye');
expect(gun.__.graph['asdf'].z).to.not.be.ok();
var now = Gun.time.is();
var ctx = Gun.union(gun, prime, function(){
expect(Gun.time.is() - now).to.be.above(100);
expect(gun.__.graph['asdf'].y).to.be('bye');
expect(gun.__.graph['asdf'].z).to.be('who');
done(); //setTimeout(function(){ done() },1);
});
});
it('future max', function(done){
var prime = {
'asdf': {
_: {'#': 'asdf', '>':{
w: Gun.time.is() + (2), // above now or upper boundary, aka future.
x: Gun.time.is() - (60 * 1000), // above now or upper boundary, aka future.
y: Gun.time.is() + (200), // above now or upper boundary, aka future.
z: Gun.time.is() + (50) // above now or upper boundary, aka future.
}},
w: true,
x: 'nothing',
y: 'farewell',
z: 'doctor who'
}
}
expect(gun.__.graph['asdf'].w).to.not.be.ok();
expect(gun.__.graph['asdf'].x).to.be('how are you?');
expect(gun.__.graph['asdf'].y).to.be('bye');
expect(gun.__.graph['asdf'].z).to.be('who');
var now = Gun.time.is();
var ctx = Gun.union(gun, prime, function(){
expect(Gun.time.is() - now).to.be.above(100);
expect(gun.__.graph['asdf'].w).to.be(true);
expect(gun.__.graph['asdf'].x).to.be('how are you?');
expect(gun.__.graph['asdf'].y).to.be('farewell');
expect(gun.__.graph['asdf'].z).to.be('doctor who');
done(); //setTimeout(function(){ done() },1);
});
});
it('two nodes', function(done){ // chat app problem where disk dropped the last data, turns out it was a union problem!
var state = Gun.time.is();
var prime = {
'sadf': {
_: {'#': 'sadf', '>':{
1: state
}},
1: {'#': 'fdsa'}
},
'fdsa': {
_: {'#': 'fdsa', '>':{
msg: state
}},
msg: "Let's chat!"
}
}
expect(gun.__.graph['sadf']).to.not.be.ok();
expect(gun.__.graph['fdsa']).to.not.be.ok();
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['sadf'][1]).to.be.ok();
expect(gun.__.graph['fdsa'].msg).to.be("Let's chat!");
done();
});
});
it('append third node', function(done){ // chat app problem where disk dropped the last data, turns out it was a union problem!
var state = Gun.time.is();
var prime = {
'sadf': {
_: {'#': 'sadf', '>':{
2: state
}},
2: {'#': 'fads'}
},
'fads': {
_: {'#': 'fads', '>':{
msg: state
}},
msg: "hi"
}
}
expect(gun.__.graph['sadf']).to.be.ok();
expect(gun.__.graph['fdsa']).to.be.ok();
var ctx = Gun.union(gun, prime, function(){
expect(gun.__.graph['sadf'][1]).to.be.ok();
expect(gun.__.graph['sadf'][2]).to.be.ok();
expect(gun.__.graph['fads'].msg).to.be("hi");
done();
});
});
it('ify null', function(){
var node = Gun.union.ify(null, 'pseudo');
expect(Gun.is.node.soul(node)).to.be('pseudo');
});
it('ify node', function(){
var graph = {
'asdf': {
_: {'#': 'asdf', '>': {
x: Gun.time.is(),
y: Gun.time.is()
}},
x: 1,
y: 2
},
'soul': {
_: {'#': 'soul', '~': 1, '>': {
'asdf': Gun.time.is()
}},
'asdf': {'#': 'asdf'}
}
}
var node = Gun.union.ify(graph, 'soul');
expect(Gun.is.node.soul(node)).to.be('soul');
expect(node.x).to.be(1);
expect(node.y).to.be(2);
});
it('ify graph', function(){
var graph = {
'asdf': {
_: {'#': 'asdf', '>': {
a: Gun.time.is() - 2,
z: Gun.time.is() - 2
}},
a: 1,
z: 1
},
'fdsa': {
_: {'#': 'fdsa', '>': {
b: Gun.time.is() - 1,
z: Gun.time.is() - 1
}},
b: 2,
z: 2
},
'sadf': {
_: {'#': 'sadf', '>': {
c: Gun.time.is(),
z: Gun.time.is() - 100
}},
c: 3,
z: 3
},
'soul': {
_: {'#': 'soul', '~': 1, '>': {
'asdf': Gun.time.is(),
'fdsa': Gun.time.is(),
'sadf': Gun.time.is(),
}},
'asdf': {'#': 'asdf'},
'fdsa': {'#': 'fdsa'},
'sadf': {'#': 'sadf'}
}
}
var node = Gun.union.ify(graph, 'soul');
expect(Gun.is.node.soul(node)).to.be('soul');
expect(node.a).to.be(1);
expect(node.b).to.be(2);
expect(node.c).to.be(3);
expect(node.z).to.be(2);
});
});
describe('API', function(){
var gopt = {wire:{put:function(n,cb){cb()},get:function(k,cb){cb()}}};
var gun = Gun();
it('gun chain separation', function(done){
var gun = Gun();
var c1 = gun.put({hello: 'world'});
var c2 = gun.put({hi: 'earth'});
c1.on(function(val){
expect(val.hi).to.not.be.ok();
});
c2.on(function(val){
expect(val.hello).to.not.be.ok();
if(done.c){ return }
done(); done.c = 1;
});
});
describe('timeywimey', function(){ return;
it('kitty', function(done){
var g1 = gun.put({hey: 'kitty'}).key('timeywimey/kitty');
var g2 = gun.get('timeywimey/kitty').on(function(val){
delete val._;
//console.log("kitty?", val);
expect(val.hey).to.be('kitty');
expect(val.hi).to.not.be.ok();
expect(val.hello).to.not.be.ok();
expect(val.foo).to.not.be.ok();
if(done.c){ return }
done(); done.c = 1;
});
});
it('kitty puppy', function(done){
var g3 = gun.put({hey: 'kitty'}).key('timeywimey/kitty/puppy');
var g4 = gun.put({hi: 'puppy'}).key('timeywimey/kitty/puppy');
var g5 = gun.get('timeywimey/kitty/puppy').on(function(val){
delete val._;
//console.log("puppy?", val);
expect(val.hey).to.be('kitty');
expect(val.hi).to.be('puppy');
if(done.c){ return }
done(); done.c = 1;
});
});
it('hello', function(done){
gun.get('timeywimey/hello').on(function(val){
delete val._;
//console.log("hello?", val);
expect(val.hello).to.be('world');
if(done.c){ return }
done(); done.c = 1;
});
gun.put({hello: 'world'}).key('timeywimey/hello');
});
it('hello foo', function(done){
gun.get('timeywimey/hello/foo').on(function(val){
delete val._;
expect(val.hello).to.be('world');
if(val.foo){
expect(val.foo).to.be('bar');
if(done.c){ return }
done(); done.c = 1;
}
});
gun.put({hello: 'world'}).key('timeywimey/hello/foo');
gun.put({foo: 'bar'}).key('timeywimey/hello/foo');
});
it('all', function(done){
gun.put({hey: 'kitty'}).key('timeywimey/all');
gun.put({hi: 'puppy'}).key('timeywimey/all');
gun.get('timeywimey/all').on(function(val){
// console.log('all', done.c, val);
expect(val.hey).to.be('kitty');
expect(val.hi).to.be('puppy');
if(val.hello){
expect(val.hello).to.be('world');
done.hello = true;
}
if(val.foo){
expect(val.foo).to.be('bar');
if(done.c || !done.hello){ return }
done(); done.c = 1;
}
});
gun.put({hello: 'world'}).key('timeywimey/all');
gun.put({foo: 'bar'}).key('timeywimey/all');
});
});
it('put', function(done){
gun.put("hello", function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('put NaN', function(done){
gun.put({num: NaN}, function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('put date', function(done){
gun.put({date: new Date()}, function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('put regex', function(done){
gun.put({num: /regex/i}, function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('put node', function(done){
gun.put({hello: "world"}, function(err, ok){
expect(err).to.not.be.ok();
done();
});
});
it('put node then value', function(done){
var ref = gun.put({hello: "world"});
ref.put('hello', function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('put node then put', function(done){
gun.put({hello: "world"}).put({goodbye: "world"}, function(err, ok){
expect(err).to.not.be.ok();
done();
});
});
it('put node with soul get soul', function(done){
gun.put({_: {'#': 'foo'}, hello: 'world'})
.get({'#': 'foo'}, function(err, node){
expect(err).to.not.be.ok();
expect(Gun.is.node.soul(node)).to.be('foo');
expect(node.hello).to.be('world');
if(done.c){ return }
done(); done.c = 1;
})
});
it('put node key get', function(done){
gun.put({hello: "key"}).key('yes/key', function(err, ok){
expect(err).to.not.be.ok();
done.w = 1; if(done.c){ return } if(done.r){ done(); done.c = 1 };
}).get('yes/key', function(err, node){ // CHANGELOG: API 0.3 BREAKING CHANGE FROM err, graph
expect(err).to.not.be.ok();
expect(Gun.is.node.soul(node)).to.be('yes/key');
expect(node.hello).to.be('key');
done.r = 1; if(done.c){ return } if(done.w){ done(); done.c = 1 };
});
});
it('put node key gun get', function(done){
gun.put({hello: "a key"}).key('yes/a/key', function(err, ok){
expect(err).to.not.be.ok();
});
gun.get('yes/a/key', function(err, node){
expect(err).to.not.be.ok();
expect(node.hello).to.be('a key');
if(done.c){ return }
done(); done.c = 1;
});
});
it('gun key', function(){ // Revisit this behavior?
try{ gun.key('fail/key') }
catch(err){
expect(err).to.be.ok();
}
});
it('get key no override', function(done){
var gun = Gun();
gun.put({cream: 'pie'}).key('cream/pie').get('cream/pie', function(err, node){
expect(Gun.is.node.soul(node)).to.be('cream/pie');
if(done.c >= 2){ return }
if(done.c){ done(); done.c = 2; return; } done.c = 1;
});
gun.get('cream/pie').key('pie/cream');
gun.get('pie/cream').put({pie: 'cream'});
});
it('get key', function(done){
gun.get('yes/key', function(err, node){
expect(err).to.not.be.ok();
expect(node.hello).to.be('key');
}).key('hello/key', function(err, ok){
expect(err).to.not.be.ok();
done.key = true;
if(done.yes){ done(); }
}).key('yes/hello', function(err, ok){
expect(err).to.not.be.ok();
done.yes = true;
if(done.key){ done(); }
});
});
it('get key null', function(done){
gun.get('yes/key').key('', function(err, ok){
expect(err).to.be.ok();
done();
});
});
it('key node has no key relations', function(done){
var gun = Gun();
gun.put({hello: 'world'}).key('hello/earth');
gun.put({continent: 'africa'}).key('hello/earth');
gun.put({place: 'asia'}).key('hello/earth');
gun.put({north: 'america'}).key('hello/galaxy');
gun.put({south: 'pole'}).key('hello/galaxy');
gun.get('hello/earth').key('hello/galaxy', function(err, ok){
expect(err).to.not.be.ok();
});
var node = gun.__.by('hello/earth').node;
expect(node['hello/galaxy']).to.not.be.ok();
gun.get('hello/earth', function(err, pseudo){
expect(pseudo.hello).to.be('world');
expect(pseudo.continent).to.be('africa');
expect(pseudo.north).to.not.be.ok();
});
var galaxy = gun.__.by('hello/galaxy').node;
expect(galaxy['hello/earth']).to.not.be.ok();
gun.get('hello/galaxy', function(err, pseudo){
if(done.c){ return }
expect(pseudo.hello).to.be('world');
expect(pseudo.south).to.be('pole');
expect(pseudo.place).to.be('asia');
expect(pseudo.continent).to.be('africa');
expect(pseudo.north).to.be('america');
done(); done.c = 1;
});
});
it('get node put node merge', function(done){
gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(node.hello).to.be('key');
done.soul = Gun.is.node.soul(node);
}).put({hi: 'you'}, function(err, ok){
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
expect(keynode.hi).to.not.be.ok();
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var node = gun.__.graph[soul];
expect(node.hello).to.be('key');
expect(node.hi).to.be('you');
}).on(function(node){
if(done.c){ return }
//expect(done.soul).to.be(Gun.is.node.soul(node)); // TODO: DISCUSSION! This has changed?
expect(node.hi).to.be('you');
expect(node.hello).to.be('key');
done(); done.c = 1;
});
});
it('get null put node never', function(done){ // TODO: GET returns nothing, and then doing a PUT?
gun.get(null, function(err, ok){
expect(err).to.be.ok();
done.err = true;
}).put({hi: 'you'}, function(err, ok){
done.flag = true;
});
setTimeout(function(){
expect(done.err).to.be.ok();
expect(done.flag).to.not.be.ok();
done();
}, 500);
});
it('get key no data put', function(done){
var gun = Gun({init: true});
gun.get('this/key/definitely/does/not/exist', function(err, data){
done.gcb = true;
done.err = err;
expect(err).to.not.be.ok();
expect(data).to.not.be.ok();
}).put({testing: 'stuff'}, function(err, ok){
done.flag = true;
});
setTimeout(function(){
expect(done.gcb).to.be.ok();
expect(done.err).to.not.be.ok();
expect(done.flag).to.not.be.ok();
done();
}, 500);
});
it('get node put node merge conflict', function(done){
gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(node.hello).to.be('key');
expect(node.hi).to.be('you');
done.soul = Gun.is.node.soul(node);
}).put({hi: 'overwritten'}, function(err, ok){
if(done.c){ return }
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var node = gun.__.graph[soul];
expect(node.hello).to.be('key');
expect(node.hi).to.be('overwritten');
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(node){
if(done.c){ return }
//expect(done.soul).to.be(Gun.is.node.soul(node)); // since put has changed chains, do we keep the pseudomerge key context?
expect(node.hello).to.be('key');
expect(node.hi).to.be('overwritten');
done.r = 1; if(done.w){ done(); done.c = 1 };
});
});
it('get key path put', function(done){
var gun = Gun().put({foo:'lol'}).key('key/path/put');
var data = gun.get('key/path/put');
data.path('foo').put('epic');
data.val(function(val, field){
expect(val.foo).to.be('epic');
expect(Gun.is.node.soul(val)).to.be('key/path/put');
done();
});
});
it('put node path', function(done){
gun.put({hello: 'world'}).path('hello', function(err, val, field){
if(done.end){ return } // it is okay for path's callback to be called multiple times.
expect(err).to.not.be.ok();
expect(field).to.be('hello');
expect(val).to.be('world');
done(); done.end = true;
});
});
it('put node path path', function(done){
gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){
if(done.end){ return } // it is okay for path's callback to be called multiple times.
expect(err).to.not.be.ok();
expect(field).to.be('little');
expect(val).to.be('world');
done(); done.end = true;
});
});
it('put node path rel', function(done){
gun.put({foo: {bar: 'lol'}}).path('foo', function(err, val, field){
if(done.end){ return } // it is okay for path's callback to be called multiple times.
expect(err).to.not.be.ok();
expect(field).to.be('foo');
expect(val.bar).to.be('lol');
done(); done.end = true;
});
});
it('get node path', function(done){
gun.get('hello/key').path('hi', function(err, val, field){
if(done.end){ return } // it is okay for path's callback to be called multiple times.
expect(err).to.not.be.ok();
expect(field).to.be('hi');
expect(val).to.be('overwritten');
done(); done.end = true;
});
});
it('put node get field', function(done){ // future feature.
var gun = Gun();
gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field');
gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){
expect(val.hi).to.be('lol');
expect(Gun.obj.has(val,'foo')).to.not.be.ok();
done();
})
});
it('get node path put value', function(done){
gun.get('hello/key', function(err, node){
expect(err).to.not.be.ok();
if(done.soul){ return }
expect(node.hi).to.be('overwritten');
done.soul = Gun.is.node.soul(node);
}).path('hi').put('again', function(err, ok){
if(done.c){ return }
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var node = gun.__.graph[done.sub = soul];
expect(node.hello).to.be('key');
expect(node.hi).to.be('again');
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(val, field){
if(done.c){ return }
expect(val).to.be('again');
expect(field).to.be('hi');
done.r = 1; if(done.w){ done(); done.c = 1 };
});
});
it('get node path put object', function(done){
gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(node.hi).to.be('again');
expect(node.hello).to.be('key');
done.soul = Gun.is.node.soul(node);
}).path('hi').put({yay: "value"}, function(err, ok){
if(done.c){ return }
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var root = gun.__.graph[soul];
expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok();
expect(Gun.is.rel(root.hi)).to.be.ok();
expect(Gun.is.rel(root.hi)).to.not.be(soul);
var node = gun.__.by(Gun.is.rel(root.hi)).node;
expect(node.yay).to.be('value');
if(done.sub){ expect(done.sub).to.be(Gun.is.rel(root.hi)) }
else { done.sub = Gun.is.rel(root.hi) }
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(node, field){
if(done.c){ return }
expect(field).to.be('hi');
expect(node.yay).to.be('value');
if(done.sub){ expect(done.sub).to.be(Gun.is.node.soul(node)) }
else { done.sub = Gun.is.node.soul(node) }
done.r = 1; if(done.w){ done(); done.c = 1 };
});
});
it('get path wire', function(done){
var gun = Gun();
var get = gun.get('shallow/path');
var path = get.path('one');
var put = path.put('good');
put.val(function(val, field){
expect(val).to.be('good');
expect(field).to.be('one');
done();
});
});
it('get path wire shallow', function(done){
var gun = Gun();
var get = gun.get('slightly/shallow/path');
var path = get.path('one');
var put = path.put({you: 'are', here: 1});
put.val(function(val, field){
expect(val.you).to.be('are');
expect(val.here).to.be(1);
expect(field).to.be('one');
done();
});
});
it('get put, put deep', function(done){
var gun = Gun();
var get = gun.get('put/deep/ish');
get.put({});
get.val(function(data){
expect(Gun.is.rel(data.very)).to.be.ok();
});
setTimeout(function(){
var put = get.put({
very: {
deep: {
ly: {
oriented: true
}
}
}
});
setTimeout(function(){
put.val(function(data){
expect(Gun.is.rel(data.very)).to.be.ok();
done.val = true;
});
var p = put.path('very');
p.put({we: 'have gone!'});
setTimeout(function(){
p.put('EXPLODE');
setTimeout(function(){
expect(done.val).to.be.ok();
done();
},5);
},50);
},50);
},50);
});
it('get path wire shallow swoop', function(done){
var gun = Gun();
var get = gun.get('slightly/shallow/path/swoop');
var path = get.path('one.two');
var put = path.put({oh: 'okay'});
put.val(function(val, field){
expect(val.oh).to.be('okay');
expect(field).to.be('two');
done();
});
});
it('get path wiring', function(done){
var gun = Gun();
var get = gun.get('deep/path');
var path = get.path('one.two');
var path3 = path.path('three');
var put = path3.put({you: 'found', the: 'bottom!'});
put.val(function(val, field){
expect(val.you).to.be('found');
expect(val.the).to.be('bottom!');
expect(field).to.be('three');
});
gun.get('deep/path').path('one.two.three.you').put('are').val(function(val, field){
expect(val).to.be('are');
expect(field).to.be('you');
done();
})
});
it('get node path put object merge isolated', function(done){
// MORAL OF THE STORY: in KEY ON.GET check for change as NODE = AT.CHANGE || GUN.__.GRAPH[AT.soul] && GUN.IS.NODE.SOUL(NODE, 'KEY') === 1; BAM!
var gun = Gun();
var put = gun.put({hello: 'key'}).key('hello/key/iso')
var get = gun.get('hello/key/iso');
var puthi = get.put({hi: 'you'});
puthi.on(function(node){
if(done.hi){ return }
expect(node.hi).to.be('you');
done.hi = 1;
});
setTimeout(function(){
var get2 = gun.get('hello/key/iso');
var path2 = get2.path('hi');
path2._.id = 'path2';
var putyay = path2.put({yay: "value"});
putyay.on(function(node, field){
expect(field).to.be('hi');
expect(node.yay).to.be('value');
});
setTimeout(function(){
var get3 = gun.get('hello/key/iso');
var path3 = get3.path('hi');
path3._.id = 'path3';
var puthappy = path3.put({happy: "faces"});
puthappy.on(function(node, field){
expect(field).to.be('hi');
expect(node.yay).to.be('value');
expect(node.happy).to.be('faces');
setTimeout(function(){
done();
},200);
});
},100);
},100);
});
it('get node path put object merge', function(done){
var g = gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(done.ref = Gun.is.rel(node.hi)).to.be.ok();
done.soul = Gun.is.node.soul(node);
});
g.path('hi').put({happy: "faces"}, function(err, ok){
if(done.c){ return }
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var root = gun.__.graph[soul];
var sub = gun.__.graph[done.ref];
expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok();
expect(Gun.is.node.soul(sub)).to.be(done.ref);
expect(sub.yay).to.be('value');
expect(sub.happy).to.be('faces');
if(done.sub){ expect(done.sub).to.be(done.ref) }
else { done.sub = done.ref }
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(node, field){
if(done.c){ return }
expect(field).to.be('hi');
expect(node.happy).to.be('faces');
expect(node.yay).to.be('value');
if(done.sub){ expect(done.sub).to.be(Gun.is.node.soul(node)) }
else { done.sub = Gun.is.node.soul(node) }
done.r = 1; if(done.w){ done(); done.c = 1 };
});
});
//return;
it('get node path put value conflict relation', function(done){
gun.get('hello/key', function(err, node){
if(done.soul){ return }
expect(err).to.not.be.ok();
expect(done.ref = Gun.is.rel(node.hi)).to.be.ok();
done.soul = Gun.is.node.soul(node);
}).path('hi').put('crushed', function(err, ok){
if(done.c){ return }
expect(err).to.not.be.ok();
var keynode = gun.__.graph[done.soul], soul;
var c = 0;
Gun.is.node(keynode, function(node, s){
soul = s;
expect(c++).to.not.be.ok();
});
var root = gun.__.graph[soul];
var sub = gun.__.graph[done.ref];
expect(root.hello).to.be('key');
expect(root.yay).to.not.be.ok();
expect(Gun.is.node.soul(sub)).to.be(done.ref);
expect(sub.yay).to.be('value');
expect(sub.happy).to.be('faces');
expect(root.hi).to.be('crushed');
done.w = 1; if(done.r){ done(); done.c = 1 };
}).on(function(val, field){
if(done.c){ return }
expect(field).to.be('hi');
expect(val).to.be('crushed');
done.r = 1; if(done.w){ done(); done.c = 1 };
});
});
it.skip('put gun node', function(done){
var mark = gun.put({age: 23, name: "Mark Nadal"});
var amber = gun.put({age: 23, name: "Amber Nadal"});
mark.path('wife').put(amber, function(err){
expect(err).to.not.be.ok();
});
mark.path('wife.name').val(function(val){
expect(val).to.be("Amber Nadal");
});
});
it('put val', function(done){
gun.put({hello: "world"}).val(function(val){
expect(val.hello).to.be('world');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('put key val', function(done){
gun.put({hello: "world"}).key('hello/world').val(function(val, field){
if(done.c){ return }
expect(val.hello).to.be('world');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get val', function(done){
gun.get('hello/world').val(function(val, field){
expect(val.hello).to.be('world');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get path', function(done){
gun.get('hello/world').path('hello').val(function(val){
expect(val).to.be('world');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get put path', function(done){
gun.get('hello/world').put({hello: 'Mark'}).path('hello').val(function(val, field){
expect(val).to.be('Mark');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get path put', function(done){
gun.get('hello/world').path('hello').put('World').val(function(val){
expect(val).to.be('World');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get empty put', function(done){
var gun = Gun({init: true});
gun.get('nothing/here').put({far: "wide"}, function(err, ok){
done.put = true;
});
gun.get({'#': 'asdfoobar'}).put({far: "wide"}, function(err, ok){
done.put2 = true;
});
setTimeout(function(){
expect(done.put).to.not.be.ok();
expect(done.put2).to.not.be.ok();
done();
}, 100)
});
it('get path empty put val', function(done){
var gun = Gun({init: true}).put({hello: "Mark"}).key('hello/world/not');
gun.get('hello/world/not').path('earth').put('mars').val(function(val){
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.not.be.ok(); // CHANGELOG: API 0.3 BREAKING CHANGE, .put is suppose to be dependent on the previous chain, which means it SHOULD NOT PUT on an empty path.
done();
}, 100);
});
it('get empty put val implicit', function(done){
var gun = Gun();
var get = gun.get('hello/imp/world');
var put = get.put({planet: 'the earth'});
put.val(function(val){
expect(val.planet).to.be('the earth');
done();
});
});
it('get empty path put val implicit split', function(done){
var gun = Gun();
var get = gun.get('hello/imp/where');
var path = get.path('where');
var put = path.put('the mars');
var val = put.val(function(val, field){
expect(field).to.be('where');
expect(val).to.be('the mars');
done();
});
});
it('get path empty put val implicit', function(done){
gun.get('hello/world').path('earth').put('mars').val(function(val, field){
expect(val).to.be('mars');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get path val', function(done){
var gun = Gun({init: true}).put({hello: "Mark"}).key('hello/world/not');
gun.get('hello/world').path('earth').put('mars');
gun.get('hello/world/not').path('earth').val(function(val){
expect(val).to.be('mars');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.not.be.ok();
done();
}, 100);
});
it('get path val implicit', function(done){
gun.get('hello/world').path('earth').val(function(val){
expect(val).to.be('mars');
expect(done.c).to.not.be.ok();
done.c = 1;
});
setTimeout(function(){
expect(done.c).to.be.ok();
done();
}, 100);
});
it('get not kick val', function(done){
gun.get("some/empty/thing").not(function(key, kick){ // that if you call not first
this.put({now: 'exists'}).key(key); // you can put stuff
}).val(function(val){ // and THEN still retrieve it.
expect(val.now).to.be('exists');
done();
});
});
it('get not kick val when it already exists', function(done){
gun.get("some/empty/thing").not(function(key, kick){
done.not = true;
this.put({now: 'THIS SHOULD NOT HAPPEN'}).key(key);
}).val(function(val){
expect(val.now).to.be('exists');
expect(done.not).to.not.be.ok();
done();
});
});
it('put path val sub', function(done){
gun.put({last: {some: 'object'}}).path('last').val(function(val){
expect(val.some).to.be('object');
done();
});
});
it('get put null', function(done){
gun.put({last: {some: 'object'}}).path('last').val(function(val, field){
expect(field).to.be('last');
expect(val.some).to.be('object');
}).put(null).val(function(val, field){
expect(field).to.be('last');
expect(val).to.be(null);
done();
});
});
it('Gun get put null', function(done){ // flip flop bug
var gun = Gun();
gun.put({last: {some: 'object'}}).path('last').val(function(val, field){
done.some = true;
expect(val.some).to.be('object');
}).put(null).val(function(val, field){
expect(val).to.be(null);
expect(done.some).to.be.ok();
done();
});
});
it('var put key path', function(done){ // contexts should be able to be saved to a variable
var foo = gun.put({foo: 'bar'}).key('foo/bar');
foo.path('hello.world.nowhere'); // this should become a sub-context, that doesn't alter the original
setTimeout(function(){
foo.path('foo').val(function(val){ // and then the original should be able to be reused later
expect(val).to.be('bar'); // this should work
done();
});
}, 500);
});
it('var get path', function(done){ // contexts should be able to be saved to a variable
var foo = gun.get('foo/bar');
foo.path('hello.world.nowhere'); // this should become a sub-context, that doesn't alter the original
setTimeout(function(){
foo.path('foo').val(function(val){ // and then the original should be able to be reused later
expect(val).to.be('bar'); // this should work
done();
});
}, 500);
});
it('get not put val path val', function(done){
var todos = gun.get("examples/list/foobar").not(function(key){
this.put({
id: 'foobar',
title: 'awesome title',
todos: {}
}).key(key);
}).val(function(data){
expect(data.id).to.be('foobar');
}).path('todos').val(function(todos, field){
expect(field).to.be('todos');
expect(todos).to.not.have.property('id');
done();
}, {empty: true});
});
it('put circular ref', function(done){
var data = {};
data[0] = "DATA!";
data.a = {c: 'd', e: 1, f: true};
data.b = {x: 2, y: 'z'};
data.a.kid = data.b;
data.b.parent = data.a;
gun.put(data, function(err, ok){
expect(err).to.not.be.ok();
}).val(function(val){
var a = gun.__.graph[Gun.is.rel(val.a)];
var b = gun.__.graph[Gun.is.rel(val.b)];
expect(Gun.is.rel(val.a)).to.be(Gun.is.node.soul(a));
expect(Gun.is.rel(val.b)).to.be(Gun.is.node.soul(b));
expect(Gun.is.rel(a.kid)).to.be(Gun.is.node.soul(b));
expect(Gun.is.rel(b.parent)).to.be(Gun.is.node.soul(a));
done();
});
});
it('gun put path and some changes node', function(done){ done.c = 0;
var ref = gun.put({
foo: {bar: 'lol'}
});
var sub = ref.path('foo').on(function(val){
done.c++;
if(val){
expect(val.extra).to.not.be.ok();
}
if(done.c === 1){
expect(val.bar).to.be('lol');
ref.put({foo: 'hi'});
return;
}
if(done.c === 2){
expect(val).to.be('hi');
done();
}
});
});
it('gun put two nodes, link one, path and detach', function(done){ done.c = 0;
// this test is not written yet!
var ref = gun.put({
foo: {bar: 'lol'}
});
var sub = ref.path('foo').on(function(val){
done.c++;
if(val){
expect(val.extra).to.not.be.ok();
}
if(done.c === 1){
expect(val.bar).to.be('lol');
ref.put({foo: 'hi'});
return;
}
if(done.c === 2){
expect(val).to.be('hi');
done();
}
});
// ref.put({foo: {extra: 'field'}});
});
it('gun put path deep primitive', function(done){
gun.put({
foo: {
bar: {
lol: true
}
}
}).path('foo.bar.lol').val(function(val){
expect(val).to.be(true);
done();
});
});
it('gun put path deep node', function(done){
gun.put({
foo: {
bar: {
lol: {ok: true}
}
}
}).path('foo.bar.lol').val(function(val){
expect(val.ok).to.be(true);
done();
});
});
it('put circular deep', function(done){
var mark = {
age: 23,
name: "Mark Nadal"
}
var amber = {
age: 23,
name: "Amber Nadal",
phd: true
}
mark.wife = amber;
amber.husband = mark;
var cat = {
age: 3,
name: "Hobbes"
}
mark.pet = cat;
amber.pet = cat;
cat.owner = mark;
cat.master = amber;
gun.put(mark, function(err, ok){
expect(err).to.not.be.ok();
}).val(function(val){
expect(val.age).to.be(23);
expect(val.name).to.be("Mark Nadal");
expect(Gun.is.rel(val.wife)).to.be.ok();
expect(Gun.is.rel(val.pet)).to.be.ok();
}).path('wife.pet.name').val(function(val){
expect(val).to.be('Hobbes');
}).back.path('pet.master').val(function(val){
expect(val.name).to.be("Amber Nadal");
expect(val.phd).to.be.ok();
expect(val.age).to.be(23);
expect(Gun.is.rel(val.pet)).to.be.ok();
done();
});
});
it('put partial sub merge', function(done){
var gun = Gun();
var mark = gun.put({name: "Mark", wife: { name: "Amber" }}).key('person/mark').val(function(mark){
done.marksoul = Gun.is.node.soul(mark);
expect(mark.name).to.be("Mark");
});
mark.put({age: 23, wife: {age: 23}});
setTimeout(function(){
mark.put({citizen: "USA", wife: {citizen: "USA"}}).val(function(mark){
expect(mark.name).to.be("Mark");
expect(mark.age).to.be(23);
expect(mark.citizen).to.be("USA");
this.path('wife').on(function(Amber){ // TODO: turn this .on back into a .val
if(done.c){ return }
expect(done.c).to.not.be.ok(); // RELATED TO BELOW #"CONTEXT NO DOUBLE EMIT".
expect(Amber.name).to.be("Amber");
expect(Amber.age).to.be(23);
expect(Amber.citizen).to.be("USA");
done();done.c=1;
});
});
}, 500);
});
it('path path', function(done){
var deep = gun.put({some: {deeply: {nested: 'value'}}});
deep.path('some.deeply.nested').val(function(val){
expect(val).to.be('value');
});
deep.path('some').path('deeply').path('nested').val(function(val){
expect(val).to.be('value');
done();
});
});
it('context null put value val error', function(done){
gun.put("oh yes", function(err){
expect(err).to.be.ok();
done();
});
});
it('context no double emit', function(done){ // annoying problem where somehow the gun.path in a put starts subscribing and firing to its context if we let get handle emitting for the chain in put.
var c = 0;
var gun = Gun();
var fo = gun.put({fo: 'bar'});
Gun.log.ba = 1;
fo.put({ba: {}}).val(function(obj, field){
c += 1;
expect(c).to.be(1);
done();
});
Gun.log.ba = 0;
var ba = fo.path('ba');
ba.put({co: 'do'});
});
var foo;
it('context null put node', function(done){
foo = gun.put({foo: 'bar'}).val(function(obj){
expect(obj.foo).to.be('bar');
done(); //setTimeout(function(){ done() },1);
});
});
it('context node put val', function(done){
// EFFECTIVELY a TIMEOUT from the previous test. NO LONGER!
foo.put('banana', function(err){
expect(err).to.be.ok();
done(); //setTimeout(function(){ done() },1);
});
});
it('context node put node', function(done){
// EFFECTIVELY a TIMEOUT from the previous test. NO LONGER!
foo.put({bar: {zoo: 'who'}}).val(function(obj, field){
//console.log("terribly terrilby unpleasant", field, obj);
expect(obj.foo).to.be('bar');
expect(Gun.is.rel(obj.bar)).to.ok();
done(); //setTimeout(function(){ done() },1);
});
});
var bar;
it('context node and field of relation put node', function(done){
// EFFECTIVELY a TIMEOUT from the previous test. NO LONGER!
bar = foo.path('bar');
expect(gleak.check()).to.not.be.ok();
bar.put({combo: 'double'}).val(function(obj, field){
//expect(obj.zoo).to.be('who');
expect(obj.combo).to.be('double');
done(); //setTimeout(function(){ done() },1);
});
});
it('context node and field put value', function(done){
// EFFECTIVELY a TIMEOUT from the previous test. NO LONGER!
var tar = foo.path('tar');
tar.put('zebra').val(function(val){
expect(val).to.be('zebra');
done(); //setTimeout(function(){ done() },1);
});
});
it('context node and field, put node', function(done){
// EFFECTIVELY a TIMEOUT from the previous test. NO LONGER!
bar.path('combo').put({another: 'node'}).val(function(obj){
expect(obj.another).to.be('node');
// double .vals here also RELATED to the #"context no double emit" but because of a faulty .not or .init system.
bar.val(function(node){
expect(Gun.is.rel(node.combo)).to.be.ok();
expect(Gun.is.rel(node.combo)).to.be(Gun.is.node.soul(obj));
done(); //setTimeout(function(){ done() },1);
});
});
});
it('path should not slowdown', function(done){
this.timeout(5000);
//this.timeout(60000);
//Gun.log.debug = 100; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
var gun = Gun({init: true}).put({
history: {}
});
//console.log("---------- setup data done -----------");
var prev, diff, max = 25, total = 100, largest = -1, gone = {};
// TODO: It would be nice if we could change these numbers for different platforms/versions of javascript interpreters so we can squeeze as much out of them.
gun.path('history').map(function(time, index){
diff = Gun.time.is() - time;
expect(gone[index]).to.not.be.ok();
gone[index] = diff;
largest = (largest < diff)? diff : largest;
//console.log(turns, index, 'largest', largest, diff);
expect(diff > max).to.not.be.ok();
});
//var p = gun.path('history');
//console.log("-------- map set up -----------");
var turns = 0;
var many = setInterval(function(){
if(turns > total || (diff || 0) > (max + 5)){
clearTimeout(many);
expect(Gun.num.is(diff)).to.be.ok();
if(done.c){ return } done(); done.c = 1;
//console.log(turns, largest);
return;
}
//if(turns === 233){ Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") }
prev = Gun.time.is();
Gun.log.base = Gun.log.ref = Gun.log.fer = prev;
var put = {}; put[turns += 1] = prev;
gun.put({history: put});
}, 1);
});
it('path rel should not slowdown', function(done){
this.timeout(5000);
//this.timeout(60000);
//Gun.log.debug = 1; console.log("~~~~~ START ~~~~~~");
var gun = Gun(gopt).put({
history: {}
});
//console.log("-------- DATA SET UP -----------");
var prev, diff, max = 100, total = 100, largest = -1, gone = {};
gun.path('history').map(function(entry, index){
//if(!entry){ return } // TODO: BUG! KNOWN BUG!!!!!!! FIX!!!!!
//console.log("WAT", index, entry);
//console.log("THE GRAPH\n", gun.__.graph);
//expect(gone[index]).to.not.be.ok();
gone[index] = diff;
diff = Gun.time.is() - (entry.time || prev);
largest = (largest < diff)? diff : largest;
//console.log('turn', turns, 'index', index, 'diff', diff, 'largest', largest);
expect(diff > max).to.not.be.ok();
});
var turns = 0;
//console.log("------------ PATH MAP SET UP --------------");
var many = setInterval(function(){
if(turns > total || diff > (max + 5)){
clearTimeout(many);
expect(Gun.num.is(diff)).to.be.ok();
if(done.c){ return } done(); done.c = 1;
return;
}
prev = Gun.time.is();
Gun.log.base = Gun.log.ref = Gun.log.fer = prev;
//if(turns === 0){ Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); }
//console.log("-------------- ", turns + 1, "-----------------");
var val = {
x: 1,
y: 1,
axis: 'y',
direction: 1,
time: prev
}
var put = {}; put[turns += 1] = val;
gun.put({history: put});
//gun.path(['history', turns += 1]).put({
},1);
});
it('val path put val', function(done){
var gun = Gun();
var al = gun.put({gender:'m', age:30, name:'alfred'}).key('user/alfred');
var beth = gun.put({gender:'f', age:22, name:'beth'}).key('user/beth');
al.val(function(a){
beth.put({friend: a}, function(err, ok){
expect(err).to.not.be.ok();
}).path('friend').val(function(aa){
expect(Gun.is.node.soul(a)).to.be(Gun.is.node.soul(aa));
done();
});
});
});
// TODO: Write a test that tests for keysoul has a key meta indicator.
// TODO: A soulsoul does not have a key meta indicator.
// TODO: Souls match their graph.
it('val path put val key', function(done){ // bug discovered from Jose's visualizer
var gun = Gun(), s = Gun.time.is(), n = function(){ return Gun.time.is() }
this.timeout(5000);
gun.put({gender:'m', age:30, name:'alfred'}).key('user/alfred');
gun.put({gender:'f', age:22, name:'beth' }).key('user/beth');
//gun.get('user/beth').path('friend').put(gun.get('user/alfred')); // ideal format which we have a future test for.
gun.get('user/alfred').val(function(a){
expect(a[Gun._.meta]['key']).to.be.ok();
gun.get('user/beth').put({friend: a}, function(err, ok){ // b - friend_of -> a
expect(err).to.not.be.ok();
var keynode = gun.__.graph['user/alfred'];
Gun.is.node(keynode, function(rel, soul){
var soulnode = gun.__.by(soul).node;
expect(soulnode[Gun._.meta]['key']).to.not.be.ok();
});
});
gun.get('user/beth').val(function(b){
gun.get('user/alfred').put({friend: b}).val(function(beth){ // a - friend_of -> b
gun.get('user/beth').put({cat: {name: "fluffy", age: 3, coat: "tabby"}}).val(function(cat){
gun.get('user/alfred').path('friend.cat').key('the/cat');
gun.get('the/cat').val(function(c){
expect(c.name).to.be('fluffy');
expect(c.age).to.be(3);
expect(c.coat).to.be('tabby');
done();
});
});
});
});
});
});
it('map', function(done){
var c = 0, set = gun.put({a: {here: 'you'}, b: {go: 'dear'}, c: {sir: '!'} });
set.map(function(obj, field){
c++;
if(field === 'a'){
expect(obj.here).to.be('you');
}
if(field === 'b'){
expect(obj.go).to.be('dear');
}
if(field === 'c'){
expect(obj.sir).to.be('!');
}
if(c === 3){
done();
}
})
});
it('key soul', function(done){
var gun = Gun();
gun.key('me', function(err, ok){
expect(err).to.not.be.ok();
var keynode = gun.__.graph['me'];
expect(keynode).to.be.ok();
Gun.is.node(keynode, function(node, soul){ done.soul = soul });
expect(done.soul).to.be('qwertyasdfzxcv');
done();
}, 'qwertyasdfzxcv');
});
it('no false positive null emit', function(done){
var gun = Gun({wire: {get: function(key, cb){
var g = {};
g[soul] = {_: {'#': soul, '>': {'a': 0}},
'a': 'b'
};
cb(null, g);
g = {};
g[soul] = {_: {'#': soul, '>': {'c': 0}},
'c': 'd'
};
cb(null, g);
g = {};
g[soul] = {_: {'#': soul }};
cb(null, g);
cb(); // false trigger!
}}}), soul = Gun.text.random();
gun.get(soul).not(function(err, ok){
done.fail = true;
}).val(function(val){
setTimeout(function(){
expect(val.a).to.be('b');
expect(val.c).to.be('d');
expect(done.fail).to.not.be.ok();
done();
},5);
});
});
it('unique val on stream', function(done){
var gun = Gun({wire: {get: function(key, cb){
if(Gun.obj.has(key, Gun._.soul)){
key = key[Gun._.soul];
var node = tmp.graph[key];
cb(null, node);
cb(null, Gun.is.node.ify({}, key));
cb(null, {});
}
}}}), tmp = {graph: {}};
tmp.graph[tmp.soul = Gun.text.random()] = tmp.node = {a: 'b', c: 'd'};
Gun.is.node.ify(tmp.node, tmp.soul);
tmp.graph['me'] = tmp.keynode = {};
Gun.obj.as(tmp.rel = {}, Gun._.soul, tmp.soul);
tmp.keynode[tmp.soul] = tmp.rel;
Gun.is.node.ify(tmp.keynode, 'me');
tmp.keynode[Gun._.meta]['key'] = 1;
gun.get('me', function(err, data){
}).val(function(val){
done.count = (done.count || 0) + 1;
setTimeout(function(){
expect(val.a).to.be('b');
expect(val.c).to.be('d');
expect(done.count).to.be(1);
done();
},5);
});
});
it('unique path val on stream', function(done){
var gun = Gun({wire: {get: function(key, cb){
var n = {};
n = {_: {'#': soul, '>': {'a': 0}},
'a': 'a'
};
cb(null, n);
n = {};
n = {_: {'#': soul, '>': {'a': 1}},
'a': 'b'
};
cb(null, n);
n = {};
n = {_: {'#': soul }};
cb(null, n);
}}}), soul = Gun.text.random();
gun.get(soul).path('a').val(function(val){
done.count = (done.count || 0) + 1;
setTimeout(function(){
expect(val).to.be('b');
expect(done.count).to.be(1);
done();
},5);
});
});
it('double not', function(done){ // from the thought tutorial
var gun = Gun(gopt).get('thoughts').not(function(key){
this.put({}).key(key);
});
setTimeout(function(){
gun.not(function(){
done.not = true;
}).val(function(){
expect(done.not).to.not.be.ok();
done();
}, {empty: true});
}, 10);
});
it('node path node path node path', function(done){
var gun = Gun(gopt);
var data = gun.get('data');
gun.put({
a: 1,
b: 2,
c: 3
}).key('data');
data.path('a', function(e, v, f){
expect(done.a).to.not.be.ok();
expect(v).to.be(1);
done.a = true;
});
data.path('b', function(e, v, f){
expect(done.b).to.not.be.ok();
expect(v).to.be(2);
done.b = true;
});
data.path('c', function(e, v, f){
expect(done.c).to.not.be.ok();
expect(v).to.be(3);
done.c = true;
});
data.put({d: 4});
setTimeout(function(){
expect(done.a).to.be.ok();
expect(done.b).to.be.ok();
expect(done.c).to.be.ok();
done();
},100);
});
it('node path obj node path obj node path obj', function(done){
var gun = Gun();
var data = gun.get('data1');
gun.put({
a: {v: 1},
b: {v: 2},
c: {v: 3}
}).key('data1');
data.path('a', function(e, v, f){
expect(done.a).to.not.be.ok();
expect(v.v).to.be(1);
done.a = true;
});
data.path('b', function(e, v, f){
expect(done.b).to.not.be.ok();
expect(v.v).to.be(2);
done.b = true;
});
data.path('c', function(e, v, f){
expect(done.c).to.not.be.ok();
expect(v.v).to.be(3);
done.c = true;
});
data.put({d: {v: 4}});
setTimeout(function(){
expect(done.a).to.be.ok();
expect(done.b).to.be.ok();
expect(done.c).to.be.ok();
done();
},100);
});
it('instance.key', function(done){
Gun().key('oye', function(err){
expect(err).to.be.ok();
done();
});
});
it('instance.on', function(done){
Gun().on();
done();
});
it('instance.path', function(done){
Gun().path('oye', function(err){
expect(err).to.be.ok();
done();
});
});
it('instance.map', function(done){
Gun().map();
done();
});
it('instance.not', function(done){
Gun().not();
done();
});
it('instance.val', function(done){
Gun().val();
done();
});
it('implicit put on empty get', function(done){
var gun = Gun().get('init');
gun.on(function(val){
expect(val.not).to.be(true);
if(done.c){ return } done(); done.c = 1;
});
gun.put({not: true});
});
it('implicit put on empty get explicit not', function(done){
var gun = Gun().get('init/not').not();
gun.on(function(val){
done.c = 1;
});
gun.put({not: true});
setTimeout(function(){
expect(done.c).to.not.be.ok();
done();
},1);
});
it('no implicit put on empty get', function(done){
var gun = Gun({init: true}).get('not/init');
gun.on(function(val){
expect(val.not).to.be(true);
if(done.c){ return } done.c = 1;
});
gun.put({not: true});
setTimeout(function(){
expect(done.c).to.not.be.ok();
done();
},1);
});
it('no implicit put on empty get explicit init', function(done){
var gun = Gun({init: true}).get('not/init/init').init();
gun.on(function(val){
expect(val.not).to.be(true);
if(done.c){ return } done(); done.c = 1;
});
gun.put({not: true})
});
it('init', function(done){
var gun = Gun().get('init/todo').init();
gun.on(function(val){
expect(val.data).to.be('initialized!');
if(done.c){ return } done(); done.c = 1;
});
gun.put({data: 'initialized!'});
});
it('init todo', function(done){
var gun = Gun(), todo = gun.get('init/todo/early');
todo.path('random1').put('eat chocolate');
todo.map().on(function(val, field){
expect(val).to.be('eat chocolate');
expect(field).to.be('random1');
if(done.c){ return } done(); done.c = 1;
});
});
it('init todo defer', function(done){
var gun = Gun(), todo = gun.get('init/todo/defer');
todo.map().on(function(val, field){
expect(val).to.be('eat chocolate');
expect(field).to.be('random1');
if(done.c){ return } done(); done.c = 1;
});
setTimeout(function(){
todo.path('random1').put('eat chocolate');
}, 100);
});
/* // CHANGELOG: API 0.3 BREAKING CHANGE, .set has been deprecated!
it('set', function(done){
done.c = 0;
var u, gun = Gun();
gun.get('set').set().set().val(function(val){
var keynode = gun.__.graph['set'];
expect(Gun.is.node.soul.ify(keynode, Gun._.key)).to.be.ok();
Gun.is.node(keynode, function(rel, soul){
rel = gun.__.by(soul).node;
expect(Gun.obj.empty(rel, Gun._.meta)).to.be.ok();
});
done.c += 1;
setTimeout(function(){
expect(done.c).to.be(1);
done()
},10);
});
});
it('root set', function(done){
var gun = Gun().set();
gun.on(function(val, field){
expect(Gun.obj.empty(val, Gun._.meta)).to.be.ok();
if(done.c){return} done(); done.c = 1;
});
});
// TODO: BUG! We need 2 more tests... without .set()... and multiple paths on the same node.
it('set multiple', function(done){ // kinda related to flip flop?
var gun = Gun().get('sets').set(), i = 0;
gun.val(function(val){
console.log("TEST 1", val);
expect(Gun.obj.empty(val, Gun._.meta)).to.be.ok();
expect(Gun.is.node.soul(val)).to.be('sets');
var keynode = gun.__.graph['sets'];
expect(Gun.obj.empty(keynode, Gun._.meta)).to.not.be.ok();
});
gun.set(1); //.set(2).set(3).set(4); // if you set an object you'd have to do a `.back`
gun.map(function(val, field){
//gun.map().val(function(val, field){ // TODO: SEAN! DON'T LET ME FORGET!
console.log("\n TEST 2+", field, val);
return;
i += 1;
expect(val).to.be(i);
if(i % 4 === 0){
setTimeout(function(){
done.i = 0;
Gun.obj.map(gun.__.graph, function(){ done.i++ });
expect(done.i).to.be(1); // make sure there isn't double.
Gun.log.verbose = false;
done()
},10);
}
});
gun.set(2);
});
*/
it('val should not print relation', function(done){ // #132
var users = Gun().get('example').path('users');
users.path(Gun.text.random()).put('bob');
users.path(Gun.text.random()).put('sam');
setTimeout(function(){
users.val(function(v){
expect(Gun.is.rel(v)).to.not.be.ok();
expect(Object.keys(v).length).to.be(3);
done();
});
},100);
});
it('peer 1 get key, peer 2 put key, peer 1 val', function(done){
var hooks = {get: function(key, cb, opt){
cb();
}, put: function(nodes, cb, opt){
Gun.union(gun1, nodes);
cb();
}},
gun1 = Gun({wire: {get: hooks.get}}).get('race')
, gun2 = Gun({wire: hooks}); //.get('race');
setTimeout(function(){
gun2.put({the: 'data'}).key('race');
setTimeout(function(){
gun1.on(function(val){
expect(val.the).to.be('data');
if(done.c){ return } done(); done.c = 1;
});
},10);
},10);
});
it('get pseudo merge', function(done){
var gun = Gun();
gun.put({a: 1, z: -1}).key('pseudo');
gun.put({b: 2, z: 0}).key('pseudo');
gun.get('pseudo').val(function(val){
expect(val.a).to.be(1);
expect(val.b).to.be(2);
expect(val.z).to.be(0);
done();
});
});
it('get pseudo merge on', function(done){
var gun = Gun();
gun.put({a: 1, z: -1}).key('pseudon');
gun.put({b: 2, z: 0}).key('pseudon');
gun.get('pseudon').on(function(val){
if(done.val){ return } // TODO: Maybe prevent repeat ons where there is no diff? (may not happen to after 1.0.0)
done.val = val;
expect(val.a).to.be(1);
expect(val.b).to.be(2);
expect(val.z).to.be(0);
done();
});
});
it('get pseudo merge across peers', function(done){ // ctx.halt
var acb, bcb, ag, bg;
Gun.on('opt').event(function(gun, o){
if(connect){ return }
gun.__.opt.wire = {get: function(key, cb, opt){
key = key[Gun._.soul];
if(o.alice){ acb = cb; ag = gun.__.graph; } else { bcb = cb; bg = gun.__.graph; }
var other = (o.alice? gun2 : gun1);
if(connect){
var node = other.__.graph[key];
cb(null, node);
} else {
cb();
}
}, put: function(nodes, cb, opt){
var other = (o.alice? gun2 : gun1);
if(connect){
Gun.union(other, nodes);
}
cb();
}}
});
function pushAtoB(key){
var node = ag[key];
bcb(null, node);
}
function pushBtoA(key){
var node = bg[key];
acb(null, node);
}
var connect, gun1 = Gun({alice: true}).get('pseudo/merge').put({hello: 'world!'})/*.not(function(key){
this.put({hello: "world!"}).key(key);
})*/, gun2;
gun1.val(function(val){
expect(val.hello).to.be('world!');
});
setTimeout(function(){
gun2 = Gun({bob: true}).get('pseudo/merge').put({hi: 'mars!'})/*.not(function(key){
this.put({hi: "mars!"}).key(key);
});*/
gun2.val(function(val){
expect(val.hi).to.be('mars!');
});
setTimeout(function(){
// CONNECT THE TWO PEERS
connect = true;
pushBtoA('pseudo/merge');
pushAtoB('pseudo/merge');
//gun1.get('pseudo/merge', null, {force: true}); // fake a browser refersh, in real world we should auto-reconnect
//gun2.get('pseudo/merge', null, {force: true}); // fake a browser refersh, in real world we should auto-reconnect
setTimeout(function(){
gun1.val(function(val){
expect(val.hello).to.be('world!');
expect(val.hi).to.be('mars!');
done.gun1 = true;
});
//return;
gun2.val(function(val){
expect(val.hello).to.be('world!');
expect(val.hi).to.be('mars!');
expect(done.gun1).to.be.ok();
Gun({});
done();
});
},10);
},10);
},10);
});
it("get map val -> map val", function(done){ // Terje's bug
var gun = Gun(); // we can test GUN locally.
var passengers = gun.get('passengers').not(function(key){
this.put({'randombob': {
name: "Bob",
location: {'lat': '37.6159', 'lng': '-128.5'},
direction: '128.2'
}, 'randomfred': {
name: "Fred",
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
direction: 'f128.2'
}}).key(key);
}); // this is now a list of passengers that we will map over.
var ctx = {n: 0, d: 0, l: 0};
passengers.map().val(function(passenger, id){
this.map().val(function(change, field){
if('name' == field){ expect(change).to.be(passenger.name); ctx.n++ }
if('direction' == field){ expect(change).to.be(passenger.direction); ctx.d++ }
if('location' == field){
delete change._; ctx.l++;
if('Bob' == passenger.name){
expect(change).to.eql({'lat': '37.6159', 'lng': '-128.5'});
} else {
expect(change).to.eql({'lat': 'f37.6159', 'lng': 'f-128.5'});
}
}
if(ctx.n == 2 && ctx.d == 2 && ctx.l == 2){ done() }
});
});
});
it("put map", function(done){
var gun = Gun();
var get = gun.get('map/that');
var put = gun.put({a: 1, b: 2, c: 3}).key('map/that');
get.map(function(v,f){
if(1 === v){ done.a = true }
if(2 === v){ done.b = true }
if(3 === v){ done.c = true }
if(done.a && done.b && done.c){
if(done.done){ return }
done(); done.done = 1;
}
});
});
it("get map map val", function(done){ // Terje's bug
var gun = Gun({init: true}); // we can test GUN locally.
var passengers = gun.get('passengers/map').not(function(key){
gun.put({randombob: {
name: "Bob",
location: {'lat': '37.6159', 'lng': '-128.5'},
direction: '128.2'
}}).key(key);
}); // this is now a list of passengers that we will map over.
var ctx = {n: 0, d: 0, l: 0};
passengers.map().map().val(function(val, field){
if('name' == field){ expect(val).to.be(!ctx.n? 'Bob' : 'Fred'); ctx.n++ }
if('direction' == field){ expect(val).to.be(!ctx.d? '128.2' : 'f128.2'); ctx.d++ }
if('location' == field){
delete val._;
if(!ctx.l){
expect(val).to.eql({'lat': '37.6159', 'lng': '-128.5'});
} else {
expect(val).to.eql({'lat': 'f37.6159', 'lng': 'f-128.5'});
}
ctx.l++;
}
if(ctx.n == 2 && ctx.d == 2 && ctx.l == 2){ done() }
});
setTimeout(function(){
passengers.put({randomfred: {
name: "Fred",
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
direction: 'f128.2'
}});
},100);
});
it("get map path val", function(done){ // Terje's bug
var gun = Gun();
var ctx = {l: -1, d: 0};
var passengers = gun.get('passengers/path').not(function(key){
this.put({randombob: {
name: "Bob",
location: {'lat': '37.6159', 'lng': '-128.5'},
direction: '128.2'
}}).key(key);
});
passengers.map().path('location.lng').val(function(val, field){
expect(field).to.be('lng');
if(ctx.l){
expect(val).to.be('-128.5');
} else {
expect(val).to.eql('f-128.5');
}
ctx.l++;
if(ctx.l){ done() }
});
setTimeout(function(){
passengers.put({randomfred: {
name: "Fred",
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
direction: 'f128.2'
}});
},100);
});
it("put path deep val -> path val", function(done){ // Terje's bug
var gun = Gun();
gun.put({you: {have: {got: {to: {be: {kidding: "me!"}}}}}}).path('you.have.got.to.be').val(function(val, field){
expect(val.kidding).to.be('me!');
this.path('kidding').val(function(val){
expect(val).to.be('me!');
done();
});
});
});
it("get set path put, map path val -> path val", function(done){ // Terje's bug
var gun = Gun();
var ctx = {l: -1, d: 0};
var passengers = gun; //.get('passengers/set/path');
passengers = passengers.put({randombob: {name: 'Bob', direction: {}}});
passengers.path('randombob.direction', function(err, ok, field){
}).put({lol: {just: 'kidding', dude: '!'}});
passengers.map().path('direction.lol').val(function(val){
this.path('just').val(function(val){
expect(val).to.be('kidding');
}).back.path('dude').val(function(val){
expect(val).to.be('!');
done();
});
})
});
it("gun get on, later gun put key", function(done){
var gun = Gun();
var keyC = gun.get('keyC').on(function(val){
expect(val.hello).to.be('world');
if(done.done){ return }
done.done = true;
done();
});
setTimeout(function(){
gun.put({hello: 'world'}).key('keyC');
}, 100);
});
it('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace //
var gun = Gun(gopt).get('players');
gun.put({
taken: true,
history: {0: {}, 1: {}}
});
gun
.path('history')
.put(null)
.back
.path('taken')
.put(false)
// TODO: BUG! There is a variation of this, where we just do `.val` rather than `gun.val` and `.val` by itself (chained off of the sub-paths) doesn't even get called. :(
gun.on(function(players){ // this val is subscribed to the original put and therefore does not get any of the sub-path listeners, therefore it gets called EARLY with the original/old data rather than waiting for the sub-path data to "finish" and then get called.
expect(players.history).to.be(null);
expect(players.taken).to.be(false);
if(done.c){ return } done(); done.c = 1;
});
});
it("gun put recursive path slowdown", function(done){
this.timeout(5000);
var gun = Gun();
gun.__.opt.wire.put = null;
function put(num, t) {
var now = new Date().getTime();
var cb;
for (var i = 1; i <= num; i++) {
if (i === num) {
cb = function (err, ok) {
console.log(num + 'ops: ' + (new Date().getTime() - now)/1000 + 's');
}
}
Gun.ify({ //hello: 'world'}, cb);
deeply: {
nested: i
}
})(cb);
}
return new Date().getTime() - now;
}
/*
put(1);
put(2);
put(10);
put(50);
put(100);
put(1000);
put(5000);*/
put(1000, true);
var gun2 = Gun();
gun2.__.opt.wire.put = null;
function put2(num, t) {
var now = new Date().getTime();
var cb;
for (var i = 1; i <= num; i++) {
if (i === num) {
cb = function () {
console.log(num + ' API ops: ' + (new Date().getTime() - now)/1000 + 's');
t && done();
}
}
gun2.put({ //hello: 'world'}, cb);
deeply: {
nested: i
}
}, cb);
}
return new Date().getTime() - now;
}
Gun.log.start = Gun.time.is();
put2(1);
put2(1000); // TODO: BUG! Interesting! If you add another 0 it causes a stack overflow! If I make Gun.time.now() not recurse then it runs but takes 4x as long. Even on the 10k ops there seems to be about a 4x overhead with the API versus raw serializer.
put2(1, true);
//put2(2);
//put2(10);
//put2(50);
//put2(100, true);
//put2(5000, true);
} );
it('choke time.now by using a while loop', function(){
var i = 10; //100000; // causes an overflow.
while(--i){
Gun.time.now();
}
});
/* // TODO: These tests should be deleted.
it("test timeout", function(done){ return done();
var i = 1000, start = Date.now();
while(i--){
setTimeout(function(){
console.log("ended in", (Date.now() - start)/1000);
},0);
}
return;
Gun.schedule(start, function(){
console.log("ended in", (Date.now() - start)/1000);
});
setImmediate(function(){
console.log("ended in", (Date.now() - start)/1000);
});
process.nextTick(function(){
console.log("ended in", (Date.now() - start)/1000);
});
});
it("test assignment", function(done){
var env = {graph: {}};
function speed(other){
var i = 10000;
while(i--){
var $ = {soul: Gun.text.random()};
var at = {node: {_: {}}};
var obj = {
deeply: {
nested: 'lol'
}
}
env.graph[at.node._[Gun._.soul] = at.soul = $.soul] = at.node
}
}
var start = Date.now();
speed();
console.log('wat', (Date.now() - start)/1000);
});
it("test fn call", function(done){
function speed(i, cb){
var r = 0;
while(i--){
if(cb){
cb(i);
} else {
r += i;
}
}
}
var start = Date.now();
speed(100000000);
console.log('no fn', (Date.now() - start)/1000);
var start = Date.now(), r = 0;
speed(100000000, function(i){ r += i });
console.log('w/ fn', (Date.now() - start)/1000);
var start = Date.now(), r = 0;
function foo(i){ r += i }
speed(100000000, foo);
console.log('w/ named fn', (Date.now() - start)/1000);
});
it("gun put recursive path slowdown MUTANT TEST", function(done){
this.timeout(30000);
Gun.chain.put = function(val, cb, opt){
var gun = this.chain(), obj;
var drift = Gun.time.now(), call = {};
cb = cb || function(){};
gun._.at('soul').event(
//(
function($){
var chain = $.gun || gun;
var ctx = {}, obj = val, $ = Gun.obj.copy($);
var hash = $.field? $.soul + $.field : ($.from? $.from + ($.at || '') : $.soul);
if(call[hash]){ return }
gun.__.meta($.soul).put = true;
call[hash] = true;
if(Gun.is.val(obj)){
if($.from && $.at){
$.soul = $.from;
$.field = $.at;
} // no else!
if(!$.field){
return cb.call(gun, {err: Gun.log("No field exists for " + (typeof obj) + "!")});
} else
if(gun.__.graph[$.soul]){
ctx.tmp = {};
ctx.tmp[ctx.field = $.field] = obj;
obj = ctx.tmp;
} else {
return cb.call(gun, {err: Gun.log("No node exists to put " + (typeof obj) + " in!")});
}
}
if(Gun.obj.is(obj)){
if($.field && !ctx.field){
ctx.tmp = {};
ctx.tmp[ctx.field = $.field] = obj;
obj = ctx.tmp;
}
Gun.ify(obj || val, function(env, cb){
var at;
if(!env || !(at = env.at) || !env.at.node){ return }
if(!at.node._){
at.node._ = {};
}
if(!Gun.is.node.soul(at.node)){
if(obj === at.obj){
env.graph[at.node._[Gun._.soul] = at.soul = $.soul] = at.node;
cb(at, at.soul);
} else {
function path(err, data){
if(at.soul){ return }
at.soul = Gun.is.node.soul(data) || Gun.is.node.soul(at.obj) || Gun.roulette.call(gun); // TODO: refactor Gun.roulette!
env.graph[at.node._[Gun._.soul] = at.soul] = at.node;
//var start = performance.now();
cb(at, at.soul);
//first = performance.now() - start;(first > .05) && console.log('here');
};
($.empty && !$.field)? path() : chain.back.path(at.path || [], path, {once: true, end: true}); // TODO: clean this up.
}
//var diff1 = (first - start), diff2 = (second - first), diff3 = (third - second);
//(diff1 || diff2 || diff3) && console.log(diff1, ' ', diff2, ' ', diff3);
}
if(!at.node._[Gun._.state]){
at.node._[Gun._.state] = {};
}
if(!at.field){ return }
at.node._[Gun._.state][at.field] = drift;
})(function(err, ify){
//console.log("chain.put PUT <----", ify.graph, '\n');
if(err || ify.err){ return cb.call(gun, err || ify.err) }
if(err = Gun.union(gun, ify.graph).err){ return cb.call(gun, err) }
if($.from = Gun.is.rel(ify.root[$.field])){ $.soul = $.from; $.field = null }
Gun.obj.map(ify.graph, function(node, soul){ Gun.union(gun, Gun.union.pseudo(soul)) });
gun._.at('soul').emit({soul: $.soul, field: $.field, key: $.key, PUT: 'SOUL', WAS: 'ON'}); // WAS ON
//return cb(null, true);
if(Gun.fns.is(ctx.hook = gun.__.opt.hooks.put)){
ctx.hook(ify.graph, function(err, data){ // now iterate through those nodes to a persistence layer and get a callback once all are saved
if(err){ return cb.call(gun, err) }
return cb.call(gun, null, data);
}, opt);
} else {
//console.Log("Warning! You have no persistence layer to save to!");
cb.call(gun, null); // This is in memory success, hardly "success" at all.
}
});
}
})
gun._.at('soul').emit({soul: Gun.roulette.call(gun), field: null, empty: true});
return gun;
}
var gun = Gun(); //.get('bug').put({});
gun.__.opt.hooks.put = null;
function put(num, t) {
var now = new Date().getTime();
var cb;
for (var i = 1; i <= num; i++) {
if (i === num) {
cb = function (err, ok) {
console.log(num + 'MUTANT ops: ' + (new Date().getTime() - now)/1000 + 's');
t && done();
}
}
gun.put({ //hello: 'world'}, cb);
deeply: {
nested: i
}
}, cb);
}
return new Date().getTime() - now;
}
//put(1, true);
//put(2);
//put(10);
//put(50);
//put(100);
//put(1000);
//put(5000);
put(10000, true);
});
*/
it("gun get empty set, path not -> this put", function(done){ // Issue #99 #101, bug in survey and trace game.
var test = {c: 0}, u;
var gun = Gun();
var game = gun.get('some/not/yet/set/put/thing').not(function(key){
gun.put({alias: {}}).key(key);
});//.set();
var me = game.path('alias').on(function(val){
if(!done.put){ return }
expect(val).to.not.be(u);
expect(val.a).to.be('b');
var meid = Gun.is.node.soul(val);
var self = this;
/*
expect(self === game).to.not.be.ok();
expect(self === me).to.be.ok();
*/
if(done.c){ return } done(); done.c = 1;
});
setTimeout(function(){
done.put = true;
me.put({a: 'b'});
},100);
});
it("gun get empty set path empty later path put multi", function(done){ // Issue #99 #101, bug in survey and trace game. // ctx.halt
done.c = 0;
var gun = Gun();
var data = gun.get('some/not/yet/set/put/thing/2');
var path = data.path('sub');
function put(d, t, f){
setTimeout(function(){
path.put(d, function(err, ok){
expect(err).to.not.be.ok();
done.c++;
if(f && done.c >= 3){
done();
}
});
},t || 10);
};
put({on: 'bus', not: 'transparent'});
put({on: null, not: 'torrent'}, 200);
put({on: 'sub', not: 'parent'}, 250, true);
});
it("ToDo", function(done){ // Simulate ToDo app!
var gun = Gun().get('example/todo/data');
gun.on(function renderToDo(val){
if(done.done){ return }
if(done.clear){
done.done = true;
expect(val[done.id]).to.not.be.ok();
return done();
}
delete val._;
Gun.obj.map(val, function(val, field){ return done.id = field; });
expect(val[done.id]).to.be('groceries');
});
setTimeout(function(){ // form submit
gun.path('random1').put("groceries");
setTimeout(function(){ // clear off element
done.clear = true;
gun.path(done.id).put(null);
},100);
},200);
});
it("gun put null path on put sub object", function(done){ // consensus4's bug
done.c = 1;
var gun = Gun();
//Gun.log.verbose = true;
var game = gun.put({board: null, teamA: null, teamB: null, turn: null}).key('the/game');
game.path('board').on(function(board, field){
expect(field).to.be('board');
if(done.c === 1){
expect(board).to.not.be.ok();
}
if(done.c === 2){
if(!board[11] || !board[22] || !board[33]){ return }
done.c++;
delete board._;
expect(board).to.be.eql({11: ' ', 22: ' ', 33: 'A'});
done();
}
});
setTimeout(function(){
done.c++;
game.put({board: {11: ' ', 22: ' ', 33: 'A'}});
},100);
});
it("get init put map -> put, foreach gun path map", function(done){ // replicate Jesse's Trace game bug
done.c = 0;
var gun = Gun(gopt).opt({init: true})
.get('players').init()
.put({
0: {
num: 0
},
1: {
num: 1
},
2: {
num: 2
},
3: {
num: 3
}
}, function(err,ok){
expect(done.c++).to.be(0);
}).val(function(p){
done.p = Gun.is.node.soul(p);
done.m = Gun.is.rel(p[0]);
expect(Gun.is.rel(p[0])).to.be.ok();
expect(Gun.is.rel(p[1])).to.be.ok();
expect(Gun.is.rel(p[2])).to.be.ok();
expect(Gun.is.rel(p[3])).to.be.ok();
})
var players = [], me;
gun.map(function (player, number) {
players[number] = player;
players[number].history = [];
if (!player.taken && !me) {
this.put({
taken: true,
history: {
0: {x: 1, y: 2}
}
}, function(err,ok){});
me = number;
}
});
Gun.list.map([0, 1, 2, 3], function (player, number) {
number = number - 1;
gun
.path(number + '.history')
.map(function (entry, logNum) {
done.c++;
players[number].history[logNum] = entry;
expect(entry.x).to.be(1);
expect(entry.y).to.be(2);
setTimeout(function(){
expect(done.c).to.be(2);
done();
},100);
});
});
});
it("gun get path empty val", function(done){ // flip flop bug
done.c = 0;
var u;
var gun = Gun(gopt);
var game = gun.get('game1/players');
var me = game.path('player1').val(function(val){
if(!done.c){ done.fail = true }
expect(val).to.not.be(u);
expect(val.x).to.be(0);
expect(val.y).to.be(0);
expect(done.fail).to.not.be.ok();
done();
});
setTimeout(function(){
done.c++;
expect(done.fail).to.not.be.ok();
me.put({x: 0, y: 0});
},10);
});
it("gun get path empty on", function(done){
done.c = 0;
var u;
var gun = Gun(gopt);
var game = gun.get('game2/players');
var me = game.path('player2').on(function(val){
if(!done.c){ done.fail = true }
expect(done.fail).to.not.be.ok();
expect(val).to.not.be(u);
if(done.done || !val.x || !val.y){ return } // it is okay if ON gets called many times, this protects against that.
// TODO: although it would be nice if we could minimize the amount of duplications. (may not happen to after 1.0.0)
expect(val.x).to.be(1);
expect(val.y).to.be(1);
done.done = true;
done();
});
setTimeout(function(){
done.c++;
expect(done.fail).to.not.be.ok();
me.put({x: 1, y: 1});
},10);
});
it("gun get path empty not", function(done){
var u;
var gun = Gun(gopt).opt({init: true})
var game = gun.get('game3/players').init();
var me = game.path('player3').not(function(field){
expect(field).to.be('player3');
done();
});
});
it("gun get path empty init", function(done){
var u;
var gun = Gun(gopt).opt({init: true});
var game = gun.get('game4/players').init();
var me = game.path('player4').init().path('alias').init().put({oh: 'awesome'}).val(function(val, field){
expect(val.oh).to.be('awesome');
expect(field).to.be('alias');
done();
})
});
it("no invalid graph", function(done){
var gun = Gun({wire:{
put: function(graph){
expect(Gun.is.graph(graph)).to.be.ok();
if(done.c){ return } if(done.on){ done(); done.c = 1 }
}
}}).get('example/todo/data/graph');
gun.on(function renderToDo(val){
done.on = true;
});
setTimeout(function(){
gun.path(Gun.text.random()).put('hoorah');
},100)
});
it("no undefined field", function(done){
var gun = Gun();
var chat = gun.get('example/chat/data/graph/field').not(function(key){
gun.put({1: {who: 'Welcome', what: "to the chat app!", when: 1}}).key(key);
});
chat.map().val(function renderToDo(val, field){
expect(field).to.be.ok();
expect(val.who).to.be.ok();
expect(val.when).to.be.ok();
expect(val.what).to.be.ok();
if(done.c >= 2){ return }
if(done.c === 1){ done() }
done.c = done.c || 0;
done.c += 1;
});
setTimeout(function(){
var msg = {};
msg.when = Gun.time.is();
msg.what = "lol!";
msg.who = "Alice";
chat.path(msg.when + '_' + Gun.text.random(4)).put(msg);
},100);
});
/* // This test didn't work for what I was wanting to test :(, will either remove it or modify it if I think of a clever solution to test what I want to test.
it.only("simulate json app", function(done){
var peers = {};
peers.server = Gun();
function wipeServer(){
peers.server = Gun();
}
var gopt = {wire:{
put: function(graph, cb){
Gun.union(peers.server, graph);
cb(null);
}
,get: function(lex, cb){
setTimeout(function(){
var soul = lex[Gun._.soul];
if(peers.localStorage){
var g = peers.localStorage;
console.log("VIA LOCALSTORAGE!", lex, g[soul]);
if(g[soul]){
var n = g[soul];
cb(null, n);
cb(null, Gun.is.node.ify({}, soul));
cb(null, {});
}
}
setTimeout(function(){
var graph = peers.server.__.graph;
console.log("VIA the SERVER!!", lex, graph[soul]);
if(!graph[soul]){
cb(null);
cb(null, {});
return;
}
var node = graph[soul];
cb(null, node);
cb(null, Gun.is.node.ify({}, soul));
cb(null, {});
},5);
},5);
}
}}
peers.gun = Gun(gopt);
function reload(){
peers.localStorage = Gun.obj.copy(peers.gun.__.graph);
peers.gun2 = Gun(gopt);
}
var ref = peers.gun.get('example/json/data/test');
setTimeout(function(){
ref.path('hello').put("value");
setTimeout(function(){
wipeServer();
reload();
setTimeout(function(){
Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~");
var ref = peers.gun2.get('example/json/data/test');
ref.on(function(data){
console.log("on!", data);
});
},100);
},100);
},100);
});
*/
it("simulate chat app", function(done){
var server = Gun();
var gopt = {wire:{
put: function(graph, cb){
Gun.union(server, graph);
cb(null);
}
,get: function(lex, cb){
setTimeout(function(){
var soul = lex[Gun._.soul];
var graph = server.__.graph;
//console.log('server replying', soul, graph);
if(!graph[soul]){
//console.log("replying to Alice...", null);
cb(null);
cb(null, {});
return;
}
var node = graph[soul];
//console.log("replying to Bob...", node);
cb(null, node);
cb(null, Gun.is.node.ify({}, soul));
cb(null, {});
},5);
}
}}
var gun = Gun(gopt);
var chat = gun.get('example/chat/data/graph/field').not(function(key){
gun.put({1: {who: 'Welcome', what: "to the chat app!", when: 1}}).key(key);
});
chat.map().val(function renderToDo(val, field){
//console.log("ALICE", field, val);
expect(field).to.be.ok();
expect(val.who).to.be.ok();
expect(val.when).to.be.ok();
expect(val.what).to.be.ok();
});
setTimeout(function(){
var gun2 = Gun(gopt);
//Gun.log.debug =1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
var chat2 = gun2.get('example/chat/data/graph/field').not(function(key){
//console.log("BOB's key", key);
gun2.put({1: {who: 'Welcome', what: "to the chat app!", when: 1}}).key(key);
});
chat2.map().val(function renderToDo(val, field){
//console.log("BOB", field, val);
expect(field).to.be.ok();
expect(val.who).to.be.ok();
expect(val.when).to.be.ok();
expect(val.what).to.be.ok();
done();
});
},100);
});
});
describe('Streams', function(){
var gun = Gun(), g = function(){
return Gun({wire: {get: ctx.get}});
}, ctx = {gen: 9, extra: 100, network: 2};
it('prep hook', function(done){
this.timeout(ctx.gen * ctx.extra);
var peer = Gun(), ref;
ctx.get = function(key, cb){
var c = 0;
cb = cb || function(){};
key = key[Gun._.soul];
if('big' !== key){ return cb(null) }
setTimeout(function badNetwork(){
c += 1;
var soul = Gun.is.node.soul(ref);
var graph = {};
var data = /*graph[soul] = */ {_: {'#': soul, '>': {}}};
if(!ref['f' + c]){
return cb(null, data), cb(null, {});
}
data._[Gun._.state]['f' + c] = ref._[Gun._.state]['f' + c];
data['f' + c] = ref['f' + c];
cb(null, data);
setTimeout(badNetwork, ctx.network);
},ctx.network);
}
ctx.get.fake = {};
for(var i = 1; i < (ctx.gen) + 1; i++){
ctx.get.fake['f'+i] = i;
ctx.length = i;
}
ctx.get.fake = Gun.is.node.ify(ctx.get.fake, 'big');
var big = peer.put(ctx.get.fake).val(function(val){
ref = val;
ctx.get({'#': 'big'}, function(err, graph){
if(Gun.obj.empty(graph)){ done() }
});
gun.opt({wire: {get: ctx.get}});
});
});
it('map chain', function(done){
var set = gun.put({a: {here: 'you'}, b: {go: 'dear'}, c: {sir: '!'} });
set.map().val(function(obj, field){
if(obj.here){
done.a = obj.here;
expect(obj.here).to.be('you');
}
if(obj.go){
done.b = obj.go;
expect(obj.go).to.be('dear');
}
if(obj.sir){
done.c = obj.sir;
expect(obj.sir).to.be('!');
}
if(done.a && done.b && done.c){
done();
}
});
});
it('map chain path', function(done){
var set = gun.put({
a: {name: "Mark",
pet: {coat: "tabby", name: "Hobbes"}
}, b: {name: "Alice",
pet: {coat: "calico", name: "Cali"}
}, c: {name: "Bob",
pet: {coat: "tux", name: "Casper"}
}
});
set.map().path('pet').val(function(obj, field){
if(obj.name === 'Hobbes'){
done.hobbes = obj.name;
expect(obj.name).to.be('Hobbes');
expect(obj.coat).to.be('tabby');
}
if(obj.name === 'Cali'){
done.cali = obj.name;
expect(obj.name).to.be('Cali');
expect(obj.coat).to.be('calico');
}
if(obj.name === 'Casper'){
done.casper = obj.name;
expect(obj.name).to.be('Casper');
expect(obj.coat).to.be('tux');
}
if(done.hobbes && done.cali && done.casper){
done();
}
});
});
it('get big on', function(done){
this.timeout(ctx.gen * ctx.extra);
var test = {c: 0, last: 0};
g().get('big').on(function(val){
if(test.done){ return console.log("hey yo! you got duplication on your ons!"); }
delete val._;
if(val['f' + (test.last + 1)]){
test.c += 1;
test.last += 1;
}
var obj = {};
for(var i = 1; i < test.c + 1; i++){
obj['f'+i] = i;
}
expect(val).to.eql(obj);
if(test.c === ctx.length){
test.done = true;
done();
}
});
});
it('get big on delta', function(done){
this.timeout(ctx.gen * ctx.extra);
var test = {c: 0, seen: {}};
g().get('big').on(function(val){
delete val._;
if(test.seen['f' + test.c]){ return }
test.seen['f' + test.c] = true;
test.c += 1;
var obj = {};
obj['f' + test.c] = test.c;
expect(val).to.eql(obj);
if(test.c === ctx.length){
done();
}
}, true);
});
it('get val', function(done){
this.timeout(ctx.gen * ctx.extra);
g().get('big').val(function(obj){
delete obj._;
expect(obj.f1).to.be(1);
expect(obj['f' + ctx.length]).to.be(ctx.length);
var raw = Gun.obj.copy(ctx.get.fake);
delete raw._;
expect(obj).to.be.eql(raw);
Gun.log.debug = 0;
done();
});
});
it('get big map val', function(done){
this.timeout(ctx.gen * ctx.extra);
var test = {c: 0, seen: {}};
g().get('big').map().val(function(val, field){
if(test.seen[field]){ return }
test.seen[field] = true;
delete val._;
expect(field).to.be('f' + (test.c += 1));
expect(val).to.be(test.c);
if(test.c === ctx.length){
done();
}
});
});
it('val emits all data', function(done){ // bug in chat app
var chat = Gun().get('example/chat/data').not(function(){
this.put({1: {who: 'Welcome', what: "to the chat app!", when: 0}}).key('example/chat/data');
});
chat.put({random1: {who: 'mark', what: "1", when: 1}});
chat.put({random2: {who: 'mark', what: "2", when: 2}});
chat.put({random3: {who: 'mark', what: "3", when: 3}});
chat.put({random4: {who: 'mark', what: "4", when: 4}});
chat.put({random5: {who: 'mark', what: "5", when: 5}});
var seen = {1: false, 2: false, 3: false, 4: false, 5: false}
setTimeout(function(){
chat.map(function(m){ }).val(function(msg, field){
var msg = Gun.obj.copy(msg);
if(msg.what){
expect(msg.what).to.be.ok();
seen[msg.when] = true;
}
if(!Gun.obj.map(seen, function(boo){ if(!boo){ return true } })){
done();
}
});
}, 100);
});
});
});