mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-05-29 18:26:36 +00:00
795 lines
24 KiB
JavaScript
795 lines
24 KiB
JavaScript
'use strict';
|
|
|
|
const _ = require('lodash');
|
|
const async = require('asyncawait/async');
|
|
const await = require('asyncawait/await');
|
|
const assert = require('assert');
|
|
const ipfsDaemon = require('orbit-common/lib/ipfs-daemon');
|
|
const ipfsAPI = require('orbit-common/lib/ipfs-api-promised');
|
|
const List = require('../src/list/OrbitList');
|
|
const List2 = require('../src/list/List');
|
|
const Node = require('../src/list/OrbitNode');
|
|
|
|
const startIpfs = async (() => {
|
|
return new Promise(async((resolve, reject) => {
|
|
const ipfsd = await(ipfsDaemon());
|
|
resolve(ipfsd.ipfs);
|
|
}));
|
|
});
|
|
|
|
let ipfs;
|
|
|
|
describe('OrbitList', async(function() {
|
|
this.timeout(5000);
|
|
|
|
before(async((done) => {
|
|
try {
|
|
ipfs = await(startIpfs());
|
|
} catch(e) {
|
|
assert.equals(e, null);
|
|
}
|
|
done();
|
|
}));
|
|
|
|
describe('Constructor', async(() => {
|
|
it('initializes member variables', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
assert.equal(list.id, 'A');
|
|
// assert.equal(list.seq, 0);
|
|
// assert.equal(list.ver, 0);
|
|
assert.equal(list._items instanceof Array, true);
|
|
assert.equal(list._currentBatch instanceof Array, true);
|
|
assert.equal(list._items.length, 0);
|
|
assert.equal(list._currentBatch.length, 0);
|
|
assert.equal(list._ipfs, ipfs);
|
|
assert.equal(list.hash, null);
|
|
done();
|
|
}));
|
|
}));
|
|
|
|
describe('ipfsHash', async(() => {
|
|
it('returns the list as ipfs hash', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
const hash = list.ipfsHash;
|
|
assert.equal(hash.startsWith('Qm'), true);
|
|
done();
|
|
}));
|
|
|
|
it('saves the list to ipfs', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
const hash = list.ipfsHash;
|
|
const l = await(ipfsAPI.getObject(ipfs, hash));
|
|
assert.equal(l.toString(), ({ Links: [], Data: '{"id":"A","seq":0,"ver":0,"items":[]}' }).toString());
|
|
done();
|
|
}));
|
|
}));
|
|
|
|
describe('fromIpfsHash', () => {
|
|
it('creates a list from ipfs hash', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
list.add("hello1")
|
|
list.add("hello2")
|
|
list.add("hello3")
|
|
const hash = list.ipfsHash;
|
|
const res = List.fromIpfsHash(ipfs, hash);
|
|
|
|
assert.equal(res.id, 'A');
|
|
// assert.equal(res.seq, 0);
|
|
// assert.equal(res.ver, 3);
|
|
assert.equal(res.items.length, 3);
|
|
// assert.equal(res.items[0].compactId, 'A.0.0');
|
|
assert.equal(res.items[0].hash, 'QmQgLATYR4Af3oCVaQ8LHumvkwtjHfZ3Tumz8RfKMxHZfo');
|
|
// assert.equal(res.items[1].compactId, 'A.0.1');
|
|
assert.equal(res.items[1].hash, 'QmTLP2MccfhZGjXHZgLL1euh2d2PkEhLf7G1pGR2Hdg4h6');
|
|
// assert.equal(res.items[2].compactId, 'A.0.2');
|
|
assert.equal(res.items[2].hash, 'QmUX8qTWAqumSxzviV4YvWyWT727pqgZX6XdViWZdoL8fC');
|
|
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('serialize', async(() => {
|
|
|
|
let list;
|
|
const expected = {
|
|
id: "A",
|
|
items: [
|
|
"QmQgLATYR4Af3oCVaQ8LHumvkwtjHfZ3Tumz8RfKMxHZfo",
|
|
"QmTLP2MccfhZGjXHZgLL1euh2d2PkEhLf7G1pGR2Hdg4h6",
|
|
"QmUX8qTWAqumSxzviV4YvWyWT727pqgZX6XdViWZdoL8fC"
|
|
]
|
|
};
|
|
|
|
before(async((done) => {
|
|
list = new List(ipfs, 'A');
|
|
list.add("hello1")
|
|
list.add("hello2")
|
|
list.add("hello3")
|
|
done();
|
|
}));
|
|
|
|
describe('asJson', async(() => {
|
|
it('presents the list as json', async((done) => {
|
|
assert.equal(JSON.stringify(list.asJson), JSON.stringify(expected));
|
|
done();
|
|
}));
|
|
}));
|
|
|
|
describe('fromJson', () => {
|
|
it('creates a list from parsed json', async((done) => {
|
|
const str = JSON.stringify(list.asJson, null, 2)
|
|
const res = List.fromJson(ipfs, JSON.parse(str));
|
|
assert.equal(res.id, 'A');
|
|
// assert.equal(res.seq, 0);
|
|
// assert.equal(res.ver, 3);
|
|
assert.equal(res.items.length, 3);
|
|
assert.equal(res.items[0].hash, 'QmQgLATYR4Af3oCVaQ8LHumvkwtjHfZ3Tumz8RfKMxHZfo');
|
|
assert.equal(res.items[1].hash, 'QmTLP2MccfhZGjXHZgLL1euh2d2PkEhLf7G1pGR2Hdg4h6');
|
|
assert.equal(res.items[2].hash, 'QmUX8qTWAqumSxzviV4YvWyWT727pqgZX6XdViWZdoL8fC');
|
|
done();
|
|
}));
|
|
});
|
|
}));
|
|
|
|
describe('items', () => {
|
|
it('returns items', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
let items = list.items;
|
|
assert.equal(list.items instanceof Array, true);
|
|
assert.equal(list.items.length, 0);
|
|
list.add("hello1")
|
|
list.add("hello2")
|
|
assert.equal(list.items instanceof Array, true);
|
|
assert.equal(list.items.length, 2);
|
|
assert.equal(list.items[0].data, 'hello1');
|
|
assert.equal(list.items[1].data, 'hello2');
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('add', () => {
|
|
it('adds an item to an empty list', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
list.add("hello1")
|
|
const item = list.items[0];
|
|
assert.equal(list.id, 'A');
|
|
// assert.equal(list.seq, 0);
|
|
// assert.equal(list.ver, 1);
|
|
assert.equal(list.items.length, 1);
|
|
assert.equal(list._currentBatch.length, 1);
|
|
assert.equal(list._items.length, 0);
|
|
assert.equal(item, list._currentBatch[0]);
|
|
assert.equal(item.id, 'A');
|
|
// assert.equal(item.seq, 0);
|
|
// assert.equal(item.ver, 0);
|
|
assert.equal(item.data, 'hello1');
|
|
done();
|
|
}));
|
|
|
|
it('adds 100 items to a list', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
const amount = 100;
|
|
|
|
for(let i = 1; i <= amount; i ++) {
|
|
list.add("hello" + i);
|
|
}
|
|
|
|
assert.equal(list.id, 'A');
|
|
assert.equal(list.items.length, amount);
|
|
|
|
const item = list.items[list.items.length - 1];
|
|
assert.equal(item.id, 'A');
|
|
assert.equal(item.data, 'hello' + amount);
|
|
assert.notEqual(item.next.length, 0);
|
|
|
|
done();
|
|
}));
|
|
|
|
it('commits a list after batch size was reached', async((done) => {
|
|
const list = new List(ipfs, 'A');
|
|
|
|
for(let i = 1; i <= List.batchSize; i ++) {
|
|
list.add("hello" + i);
|
|
}
|
|
|
|
assert.equal(list.id, 'A');
|
|
// assert.equal(list.seq, 0);
|
|
// assert.equal(list.ver, List.batchSize);
|
|
assert.equal(list.items.length, List.batchSize);
|
|
assert.equal(list._currentBatch.length, List.batchSize);
|
|
assert.equal(list._items.length, 0);
|
|
|
|
const item = list.items[list.items.length - 1];
|
|
assert.equal(item.id, 'A');
|
|
// assert.equal(item.seq, 0);
|
|
assert.equal(list.items.length, List.batchSize);
|
|
assert.equal(item.data, 'hello' + List.batchSize);
|
|
assert.notEqual(item.next.length, 0);
|
|
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('join', () => {
|
|
it('joins unique items', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
|
|
list1.add("helloA3")
|
|
|
|
list1.join(list2);
|
|
list1.join(list2);
|
|
|
|
list1.add("helloA4")
|
|
list1.add("helloA5")
|
|
|
|
const lastItem = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.items.length, 7);
|
|
assert.equal(lastItem.next.length, 1);
|
|
assert.equal(lastItem.next[0].hash, 'QmPT7qgkysupMuMf2k8yESBL8A55Cva9Y8pqTuA1AMWB4m');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next head when adding a new element', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list1.add("helloA3")
|
|
|
|
assert.equal(list1._currentBatch.length, 3);
|
|
assert.equal(list1._currentBatch[0].next.length, 0);
|
|
assert.equal(list1._currentBatch[1].next.length, 1);
|
|
assert.equal(list1._currentBatch[1].next[0].hash, 'QmQQhCyFHWAwNm7k5CbDF5iKuHfT2VJU5qUkncQDNAfTbL');
|
|
assert.equal(list1._currentBatch[2].next.length, 1);
|
|
assert.equal(list1._currentBatch[2].next[0].hash, 'QmbKmxJv6mhGvvUQwU3A5BBWvpBMVvGkpFr5AMrrqib6EH');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next heads (two) after a join', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
list1.add("helloA2")
|
|
|
|
assert.equal(list1._currentBatch.length, 1);
|
|
assert.equal(list1._currentBatch[0].next.length, 2);
|
|
// assert.equal(list1._currentBatch[0].next[1].compactId, 'A.0.0');
|
|
assert.equal(list1._currentBatch[0].next[1].hash, 'QmQQhCyFHWAwNm7k5CbDF5iKuHfT2VJU5qUkncQDNAfTbL');
|
|
// assert.equal(list1._currentBatch[0].next[0].compactId, 'B.0.1');
|
|
assert.equal(list1._currentBatch[0].next[0].hash, 'QmUnaa1dT2FEYmK1nDD5fJ53Pd2iEDtGL3oLM5M7VLBqHJ');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next head (one) after a join', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
|
|
list1.add("helloA2")
|
|
list1.add("helloA3")
|
|
|
|
assert.equal(list1._currentBatch.length, 2);
|
|
assert.equal(list1._currentBatch[1].next.length, 1);
|
|
// assert.equal(list1._currentBatch[1].next[0].compactId, 'A.1.0');
|
|
assert.equal(list1._currentBatch[1].next[0].hash, 'QmaGPFKz6qJLuLhUFN2J48FVZttVF2y2gmgU3666H21BWQ');
|
|
assert.equal(list1._currentBatch[0].next.length, 2);
|
|
// assert.equal(list1._currentBatch[0].next[0].compactId, 'B.0.1');
|
|
assert.equal(list1._currentBatch[0].next[0].hash, 'QmUnaa1dT2FEYmK1nDD5fJ53Pd2iEDtGL3oLM5M7VLBqHJ');
|
|
// assert.equal(list1._currentBatch[0].next[1].compactId, 'A.0.0');
|
|
assert.equal(list1._currentBatch[0].next[1].hash, 'QmQQhCyFHWAwNm7k5CbDF5iKuHfT2VJU5qUkncQDNAfTbL');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next heads after two joins', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
|
|
list1.add("helloA3")
|
|
|
|
list1.join(list2);
|
|
|
|
list1.add("helloA4")
|
|
list1.add("helloA5")
|
|
|
|
const lastItem = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.items.length, 7);
|
|
assert.equal(lastItem.next.length, 1);
|
|
// assert.equal(lastItem.next[0].compactId, 'A.2.0');
|
|
assert.equal(lastItem.next[0].hash, 'QmPT7qgkysupMuMf2k8yESBL8A55Cva9Y8pqTuA1AMWB4m');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next heads after multiple joins', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
const list3 = new List(ipfs, 'C');
|
|
const list4 = new List(ipfs, 'D');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
|
|
list3.add("helloC1")
|
|
list4.add("helloD1")
|
|
list1.join(list3);
|
|
|
|
list1.add("helloA3")
|
|
list2.join(list1);
|
|
list1.join(list2);
|
|
list2.join(list4);
|
|
|
|
list4.add("helloD2")
|
|
list4.add("helloD3")
|
|
list1.add("helloA4")
|
|
list1.join(list4);
|
|
|
|
list1.add("helloA5")
|
|
|
|
const lastItem = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.items.length, 11);
|
|
assert.equal(lastItem.next.length, 2);
|
|
// assert.equal(lastItem.next[1].compactId, 'A.4.0');
|
|
assert.equal(lastItem.next[1].hash, 'QmdyS6VUP5wAENpdT1sp6o1JJwMaKajPg1W441MD71r4pE');
|
|
// assert.equal(lastItem.next[0].compactId, 'D.0.2');
|
|
assert.equal(lastItem.next[0].hash, 'QmfWbsDTKd3zhRoJZ2oGeBYmgsnerK3SmFYXZtydgADec7');
|
|
done();
|
|
}));
|
|
|
|
it('joins list of one item with list of two items', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
|
|
const lastItem = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.id, 'A');
|
|
// assert.equal(list1.seq, 1);
|
|
// assert.equal(list1.ver, 0);
|
|
assert.equal(list1._currentBatch.length, 0);
|
|
assert.equal(list1._items.length, 3);
|
|
assert.equal(lastItem.id, 'B');
|
|
// assert.equal(lastItem.seq, 0);
|
|
// assert.equal(lastItem.ver, 1);
|
|
assert.equal(lastItem.data, 'helloB2');
|
|
done();
|
|
}));
|
|
|
|
it('joins lists two ways', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
list2.join(list1);
|
|
|
|
const lastItem1 = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.id, 'A');
|
|
// assert.equal(list1.seq, 1);
|
|
// assert.equal(list1.ver, 0);
|
|
assert.equal(list1._currentBatch.length, 0);
|
|
assert.equal(list1._items.length, 4);
|
|
assert.equal(lastItem1.id, 'B');
|
|
// assert.equal(lastItem1.seq, 0);
|
|
// assert.equal(lastItem1.ver, 1);
|
|
assert.equal(lastItem1.data, 'helloB2');
|
|
|
|
const lastItem2 = list2.items[list2.items.length - 1];
|
|
|
|
assert.equal(list2.id, 'B');
|
|
// assert.equal(list2.seq, 2);
|
|
// assert.equal(list2.ver, 0);
|
|
assert.equal(list2._currentBatch.length, 0);
|
|
assert.equal(list2._items.length, 4);
|
|
assert.equal(lastItem2.id, 'A');
|
|
// assert.equal(lastItem2.seq, 0);
|
|
// assert.equal(lastItem2.ver, 1);
|
|
assert.equal(lastItem2.data, 'helloA2');
|
|
done();
|
|
}));
|
|
|
|
it('joins lists twice', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
|
|
list1.add("helloA1")
|
|
list2.add("helloB1")
|
|
list2.join(list1);
|
|
|
|
list1.add("helloA2")
|
|
list2.add("helloB2")
|
|
list2.join(list1);
|
|
|
|
const secondItem = list2.items[1];
|
|
const lastItem = list2.items[list2.items.length - 1];
|
|
|
|
assert.equal(list2.id, 'B');
|
|
// assert.equal(list2.seq, 2);
|
|
// assert.equal(list2.ver, 0);
|
|
assert.equal(list2._currentBatch.length, 0);
|
|
assert.equal(list2._items.length, 4);
|
|
assert.equal(secondItem.id, 'A');
|
|
// assert.equal(secondItem.seq, 0);
|
|
// assert.equal(secondItem.ver, 0);
|
|
assert.equal(secondItem.data, 'helloA1');
|
|
assert.equal(lastItem.id, 'A');
|
|
// assert.equal(lastItem.seq, 0);
|
|
// assert.equal(lastItem.ver, 1);
|
|
assert.equal(lastItem.data, 'helloA2');
|
|
done();
|
|
}));
|
|
|
|
it('joins 4 lists to one', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
const list3 = new List(ipfs, 'C');
|
|
const list4 = new List(ipfs, 'D');
|
|
|
|
list1.add("helloA1")
|
|
list2.add("helloB1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB2")
|
|
list3.add("helloC1")
|
|
list4.add("helloD1")
|
|
list3.add("helloC2")
|
|
list4.add("helloD2")
|
|
list1.join(list2);
|
|
list1.join(list3);
|
|
list1.join(list4);
|
|
|
|
const secondItem = list1.items[1];
|
|
const lastItem = list1.items[list1.items.length - 1];
|
|
|
|
assert.equal(list1.id, 'A');
|
|
// assert.equal(list1.seq, 3);
|
|
// assert.equal(list1.ver, 0);
|
|
assert.equal(list1._currentBatch.length, 0);
|
|
assert.equal(list1._items.length, 8);
|
|
assert.equal(secondItem.id, 'A');
|
|
// assert.equal(secondItem.seq, 0);
|
|
// assert.equal(secondItem.ver, 1);
|
|
assert.equal(secondItem.data, 'helloA2');
|
|
assert.equal(lastItem.id, 'D');
|
|
// assert.equal(lastItem.seq, 0);
|
|
// assert.equal(lastItem.ver, 1);
|
|
assert.equal(lastItem.data, 'helloD2');
|
|
done();
|
|
}));
|
|
|
|
it('joins lists from 4 lists', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
const list3 = new List(ipfs, 'C');
|
|
const list4 = new List(ipfs, 'D');
|
|
|
|
list1.add("helloA1")
|
|
list1.join(list2);
|
|
list2.add("helloB1")
|
|
list2.join(list1);
|
|
|
|
list1.add("helloA2")
|
|
list2.add("helloB2")
|
|
list1.join(list3);
|
|
list3.join(list1);
|
|
|
|
list3.add("helloC1")
|
|
list4.add("helloD1")
|
|
|
|
list3.add("helloC2")
|
|
list4.add("helloD2")
|
|
|
|
list1.join(list3);
|
|
list1.join(list2);
|
|
list4.join(list2);
|
|
list4.join(list1);
|
|
list4.join(list3);
|
|
|
|
list4.add("helloD3")
|
|
list4.add("helloD4")
|
|
|
|
const secondItem = list4.items[1];
|
|
const lastItem1 = list4._items[list4._items.length - 1];
|
|
const lastItem2 = list4.items[list4.items.length - 1];
|
|
|
|
assert.equal(list4.id, 'D');
|
|
// assert.equal(list4.seq, 7);
|
|
// assert.equal(list4.ver, 2);
|
|
assert.equal(list4._currentBatch.length, 2);
|
|
assert.equal(list4._items.length, 8);
|
|
assert.equal(secondItem.id, 'D');
|
|
// assert.equal(secondItem.seq, 0);
|
|
// assert.equal(secondItem.ver, 1);
|
|
assert.equal(secondItem.data, 'helloD2');
|
|
assert.equal(lastItem1.id, 'C');
|
|
// assert.equal(lastItem1.seq, 3);
|
|
// assert.equal(lastItem1.ver, 1);
|
|
assert.equal(lastItem1.data, 'helloC2');
|
|
assert.equal(lastItem2.id, 'D');
|
|
// assert.equal(lastItem2.seq, 7);
|
|
// assert.equal(lastItem2.ver, 1);
|
|
assert.equal(lastItem2.data, 'helloD4');
|
|
done();
|
|
}));
|
|
|
|
it('fetches items from history on join', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'AAA');
|
|
|
|
const count = 32;
|
|
for(let i = 1; i < count + 1; i ++) {
|
|
list1.add("first " + i);
|
|
list2.add("second " + i);
|
|
}
|
|
|
|
const hash1 = list1.ipfsHash;
|
|
const hash2 = list2.ipfsHash;
|
|
|
|
const final = new List(ipfs, 'B');
|
|
const other1 = List.fromIpfsHash(ipfs, hash1);
|
|
const other2 = List.fromIpfsHash(ipfs, hash2);
|
|
final.join(other1);
|
|
|
|
assert.equal(_.includes(final.items.map((a) => a.hash), undefined), false);
|
|
assert.equal(final.items.length, count);
|
|
assert.equal(final.items[0].data, "first 1");
|
|
assert.equal(final.items[final.items.length - 1].data, "first " + count);
|
|
|
|
final.join(other2);
|
|
assert.equal(final.items.length, count * 2);
|
|
assert.equal(final.items[0].data, "second 1");
|
|
assert.equal(final.items[final.items.length - 1].data, "second " + count);
|
|
done();
|
|
}));
|
|
|
|
it('orders fetched items correctly', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'AAA');
|
|
const final = new List(ipfs, 'B');
|
|
|
|
const count = List.batchSize * 3;
|
|
for(let i = 1; i < (count * 2) + 1; i ++)
|
|
list1.add("first " + i);
|
|
|
|
const hash1 = list1.ipfsHash;
|
|
const other1 = List.fromIpfsHash(ipfs, hash1);
|
|
final.join(other1);
|
|
|
|
assert.equal(final.items[0].data, "first 1");
|
|
assert.equal(final.items[final.items.length - 1].data, "first " + count * 2);
|
|
assert.equal(final.items.length, count * 2);
|
|
|
|
// Second batch
|
|
for(let i = 1; i < count + 1; i ++)
|
|
list2.add("second " + i);
|
|
|
|
const hash2 = list2.ipfsHash;
|
|
const other2 = List.fromIpfsHash(ipfs, hash2);
|
|
final.join(other2);
|
|
|
|
// console.log(final.items.map((e) => e.comptactId))
|
|
assert.equal(final.items.length, count + count * 2);
|
|
assert.equal(final.items[0].data, "second 1");
|
|
assert.equal(final.items[1].data, "second 2");
|
|
assert.equal(final.items[final.items.length - 1].data, "second " + count);
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('findHeads', () => {
|
|
it('finds the next head', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
const list3 = new List(ipfs, 'C');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
list1.add("helloA3")
|
|
list1.add("helloA4")
|
|
list3.add("helloC1")
|
|
list3.add("helloC2")
|
|
list2.join(list3);
|
|
list2.add("helloB3")
|
|
list1.join(list2);
|
|
list1.add("helloA5")
|
|
list1.add("helloA6")
|
|
|
|
const heads = List2.findHeads(list1.items)
|
|
assert.equal(heads.length, 1);
|
|
assert.equal(heads[0].hash, 'QmfUmywxAP8ZXNkxN1CJJ3UsbmEracdeDCzaZzid9zwoe9');
|
|
done();
|
|
}));
|
|
|
|
it('finds the next heads', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
const list2 = new List(ipfs, 'B');
|
|
const list3 = new List(ipfs, 'C');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list1.join(list2);
|
|
list1.add("helloA3")
|
|
list1.add("helloA4")
|
|
list3.add("helloC1")
|
|
list3.add("helloC2")
|
|
list2.join(list3);
|
|
list2.add("helloB3")
|
|
list1.join(list2);
|
|
|
|
const heads = List2.findHeads(list1.items)
|
|
assert.equal(heads.length, 2);
|
|
assert.equal(heads[0].hash, 'QmT8oHPp2x5t5sKy2jw3ZXKihm1danLbmHMbQ6nnzWRdj6');
|
|
assert.equal(heads[1].hash, 'QmPT7qgkysupMuMf2k8yESBL8A55Cva9Y8pqTuA1AMWB4m');
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('is a CRDT', () => {
|
|
it('join is associative', async((done) => {
|
|
let list1 = new List(ipfs, 'A');
|
|
let list2 = new List(ipfs, 'B');
|
|
let list3 = new List(ipfs, 'C');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list3.add("helloC1")
|
|
list3.add("helloC2")
|
|
|
|
// a + (b + c)
|
|
list2.join(list3);
|
|
list1.join(list2);
|
|
|
|
const res1 = list1.items.map((e) => e.hash).join(",");
|
|
|
|
list1 = new List(ipfs, 'A');
|
|
list2 = new List(ipfs, 'B');
|
|
list3 = new List(ipfs, 'C');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
list3.add("helloC1")
|
|
list3.add("helloC2")
|
|
|
|
// (a + b) + c
|
|
list1.join(list2);
|
|
list1.join(list3);
|
|
|
|
const res2 = list1.items.map((e) => e.hash).join(",");
|
|
|
|
// associativity: a + (b + c) == (a + b) + c
|
|
const len = (46 + 1) * 6- 1; // 46 == ipfs hash, +1 == .join(","), * 4 == number of items, -1 == last item doesn't get a ',' from .join
|
|
assert.equal(res1.length, len)
|
|
assert.equal(res2.length, len)
|
|
assert.equal(res1, res2);
|
|
done();
|
|
}));
|
|
|
|
it('join is commutative', async((done) => {
|
|
let list1 = new List(ipfs, 'A');
|
|
let list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.join(list1);
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
|
|
// b + a
|
|
list2.join(list1);
|
|
|
|
const res1 = list2.items.map((e) => e.hash).join(",");
|
|
|
|
list1 = new List(ipfs, 'A');
|
|
list2 = new List(ipfs, 'B');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list2.join(list1);
|
|
list2.add("helloB1")
|
|
list2.add("helloB2")
|
|
|
|
// a + b
|
|
list1.join(list2);
|
|
|
|
const res2 = list1.items.map((e) => e.hash).join(",");
|
|
|
|
// commutativity: a + (b + c) == (a + b) + c
|
|
const len = (46 + 1) * 4 - 1; // 46 == ipfs hash, +1 == .join(","), * 4 == number of items, -1 == last item doesn't get a ',' from .join
|
|
assert.equal(res1.length, len)
|
|
assert.equal(res2.length, len)
|
|
assert.equal(res1, res2);
|
|
done();
|
|
}));
|
|
|
|
|
|
it('join is idempotent', async((done) => {
|
|
const list1 = new List(ipfs, 'A');
|
|
list1.add("helloA1")
|
|
list1.add("helloA2")
|
|
list1.add("helloA3")
|
|
|
|
const list2 = new List(ipfs, 'A');
|
|
list2.add("helloA1")
|
|
list2.add("helloA2")
|
|
list2.add("helloA3")
|
|
|
|
// idempotence: a + a = a
|
|
list1.join(list2);
|
|
|
|
assert.equal(list1.id, 'A');
|
|
// assert.equal(list1.seq, 1);
|
|
// assert.equal(list1.ver, 0);
|
|
assert.equal(list1.items.length, 3);
|
|
// assert.equal(list1.items[0].ver, 0);
|
|
// assert.equal(list1.items[1].ver, 1);
|
|
// assert.equal(list1.items[2].ver, 2);
|
|
done();
|
|
}));
|
|
});
|
|
|
|
describe('clear', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('_fetchHistory', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('_fetchRecursive', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('_insert', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('_commit', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe('isReferencedInChain', () => {
|
|
it('TODO', (done) => {
|
|
done();
|
|
});
|
|
});
|
|
|
|
|
|
}));
|