orbit-db/test/orbit-client-tests.js

686 lines
19 KiB
JavaScript

'use strict';
const _ = require('lodash');
const assert = require('assert');
const async = require('asyncawait/async');
const await = require('asyncawait/await');
const OrbitClient = require('../src/Client');
// Orbit
const host = 'localhost';
const port = 3333;
const username = 'testrunner';
const password = '';
describe('Orbit Client', function() {
this.timeout(15000);
let client, db;
let items = [];
let channel = 'abcdefgh';
before(async((done) => {
client = await(OrbitClient.connect(host, port, username, password, true));
db = client.channel(channel, '', false);
db.delete();
done();
}));
after(async((done) => {
if(db) db.delete();
if(client) client.disconnect();
done();
}));
describe('Add events', function() {
let items2 = [];
const itemCount = 5;
beforeEach(async((done) => {
db.delete();
done();
}));
after(async((done) => {
db.delete();
done();
}));
it('adds an item to an empty channel', async((done) => {
const head = db.add('hello');
assert.notEqual(head, null);
assert.equal(head.startsWith('Qm'), true);
assert.equal(head.length, 46);
done();
}));
it('adds a new item to a channel with one item', async((done) => {
const head = db.iterator().collect();
const second = db.add('hello');
assert.notEqual(second, null);
assert.notEqual(second, head);
assert.equal(second.startsWith('Qm'), true);
assert.equal(second.length, 46);
done();
}));
it('adds five items', async((done) => {
for(let i = 0; i < 5; i ++) {
let hash = db.add('hello');
assert.notEqual(hash, null);
assert.equal(hash.startsWith('Qm'), true);
assert.equal(hash.length, 46);
}
done();
}));
it('adds an item that is > 256 bytes', async((done) => {
let msg = new Buffer(1024);
msg.fill('a')
const hash = await(db.add(msg.toString()));
assert.notEqual(hash, null);
assert.equal(hash.startsWith('Qm'), true);
assert.equal(hash.length, 46);
done();
}));
});
describe('Delete events', function() {
beforeEach(async((done) => {
db.delete();
let items = db.iterator().collect();
assert.equal(items.length, 0);
done();
}));
after(async((done) => {
db.delete();
done();
}));
it('deletes an item when only one item in the database', async((done) => {
const head = db.add('hello1');
let item = db.iterator().collect();
const delop = db.del(head);
const items = db.iterator().collect();
assert.equal(delop.startsWith('Qm'), true);
assert.equal(items.length, 0);
done();
}));
it('deletes an item when two items in the database', async((done) => {
db.delete();
db.add('hello1');
const head = db.add('hello2');
db.del(head);
const items = db.iterator().collect();
assert.equal(items.length, 1);
// assert.equal(items[0].op, 'ADD');
assert.equal(items[0].value, 'hello1');
done();
}));
it('deletes an item between adds', async((done) => {
const head = db.add('hello1');
db.add('hello2');
db.del(head);
db.add('hello3');
const items = db.iterator().collect();
assert.equal(items.length, 1);
assert.equal(items[0].key.startsWith('Qm'), true);
assert.equal(items[0].hash.startsWith('Qm'), true);
// assert.equal(items[0].op, 'ADD');
assert.equal(items[0].value, 'hello3');
done();
}));
});
describe('Iterator', function() {
let items = [];
let items2 = [];
const itemCount = 5;
beforeEach(async((done) => {
db.delete();
items2 = [];
for(let i = 0; i < itemCount; i ++) {
const hash = db.add('hello' + i);
items2.push(hash);
}
done();
}));
afterEach(async((done) => {
db.delete();
done();
}));
describe('Defaults', function() {
it('returns an iterator', async((done) => {
const iter = db.iterator();
const next = iter.next().value;
assert.notEqual(iter, null);
assert.notEqual(next, null);
done();
}));
it('returns an item with the correct structure', async((done) => {
const iter = db.iterator();
const next = iter.next().value;
assert.notEqual(next, null);
assert.notEqual(next.key, null);
// assert.equal(next.op, 'ADD');
assert.equal(next.key.startsWith('Qm'), true);
assert.equal(next.hash.startsWith('Qm'), true);
assert.equal(next.value, 'hello4');
done();
}));
it('implements Iterator interface', async((done) => {
const iter = db.iterator({ limit: -1 });
let messages = [];
for(let i of iter)
messages.push(i.key);
assert.equal(messages.length, items2.length);
done();
}));
it('returns 1 item as default', async((done) => {
const iter = db.iterator();
const first = iter.next().value;
const second = iter.next().value;
assert.equal(first.key, items2[items2.length - 1]);
assert.equal(second, null);
assert.equal(first.value, 'hello4');
done();
}));
});
describe('Collect', function() {
let items2;
before(async((done) => {
db.delete();
items2 = [];
for(let i = 0; i < itemCount; i ++) {
const hash = db.add('hello' + i);
items2.push(hash);
}
done();
}));
// after(async((done) => {
// db.delete();
// items2 = [];
// done();
// }));
it('returns all items', async((done) => {
const messages = db.iterator({ limit: -1 }).collect();
assert.equal(messages.length, items2.length);
assert.equal(messages[0].value, 'hello0');
assert.equal(messages[messages.length - 1].value, 'hello4');
done();
}));
it('returns 1 item', async((done) => {
const messages = db.iterator().collect();
assert.equal(messages.length, 1);
done();
}));
it('returns 3 items', async((done) => {
const messages = db.iterator({ limit: 3 }).collect();
assert.equal(messages.length, 3);
done();
}));
});
describe('Options: limit', function() {
let items2;
beforeEach(async((done) => {
db.delete();
items2 = [];
for(let i = 1; i <= itemCount; i ++) {
const hash = db.add('hello' + i);
items2.push(hash);
}
done();
}));
// after(async((done) => {
// db.delete();
// items2 = [];
// done();
// }));
it('returns 1 item when limit is 0', async((done) => {
const iter = db.iterator({ limit: 1 });
const first = iter.next().value;
const second = iter.next().value;
assert.equal(first.key, _.last(items2));
assert.equal(second, null);
done();
}));
it('returns 1 item when limit is 1', async((done) => {
const iter = db.iterator({ limit: 1 });
const first = iter.next().value;
const second = iter.next().value;
assert.equal(first.key, _.last(items2));
assert.equal(second, null);
done();
}));
it('returns 3 items', async((done) => {
const iter = db.iterator({ limit: 3 });
const first = iter.next().value;
const second = iter.next().value;
const third = iter.next().value;
const fourth = iter.next().value;
assert.equal(first.key, items2[items2.length - 3]);
assert.equal(second.key, items2[items2.length - 2]);
assert.equal(third.key, items2[items2.length - 1]);
assert.equal(fourth, null);
done();
}));
it('returns all items', async((done) => {
const messages = db.iterator({ limit: -1 })
.collect()
.map((e) => e.key);
messages.reverse();
assert.equal(messages.length, items2.length);
assert.equal(messages[0], items2[items2.length - 1]);
done();
}));
it('returns all items when limit is bigger than -1', async((done) => {
const messages = db.iterator({ limit: -300 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, items2.length);
assert.equal(messages[0], items2[0]);
done();
}));
it('returns all items when limit is bigger than number of items', async((done) => {
const messages = db.iterator({ limit: 300 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, items2.length);
assert.equal(messages[0], items2[0]);
done();
}));
});
describe('Options: reverse', function() {
let items2;
beforeEach(async((done) => {
db.delete();
items2 = [];
for(let i = 1; i <= itemCount; i ++) {
const hash = db.add('hello' + i);
items2.push(hash);
}
done();
}));
it('returns all items reversed', async((done) => {
const messages = db.iterator({ limit: -1, reverse: true })
.collect()
.map((e) => e.key);
assert.equal(messages.length, items2.length);
assert.equal(messages[0], items2[0]);
done();
}));
});
describe('Options: ranges', function() {
let items2;
beforeEach(async((done) => {
db.delete();
items2 = [];
for(let i = 1; i <= itemCount; i ++) {
const hash = db.add('hello' + i);
items2.push(hash);
}
done();
}));
describe('gt & gte', function() {
it('returns 1 item when gte is the head', async((done) => {
const messages = db.iterator({ gte: _.last(items2), limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 1);
assert.equal(messages[0], _.last(items2));
done();
}));
it('returns 0 items when gt is the head', async((done) => {
const messages = db.iterator({ gt: _.last(items2) }).collect();
assert.equal(messages.length, 0);
done();
}));
it('returns 2 item when gte is defined', async((done) => {
const gte = items2[items2.length - 2];
const messages = db.iterator({ gte: gte, limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 2);
assert.equal(messages[0], items2[items2.length - 2]);
assert.equal(messages[1], items2[items2.length - 1]);
done();
}));
it('returns all items when gte is the root item', async((done) => {
const messages = db.iterator({ gte: items2[0], limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, items2.length);
assert.equal(messages[0], items2[0]);
assert.equal(messages[messages.length - 1], _.last(items2));
done();
}));
it('returns items when gt is the root item', async((done) => {
const messages = db.iterator({ gt: items2[0], limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, itemCount - 1);
assert.equal(messages[0], items2[1]);
assert.equal(messages[3], _.last(items2));
done();
}));
it('returns items when gt is defined', async((done) => {
const messages = db.iterator({ limit: -1})
.collect()
.map((e) => e.key);
const gt = messages[2];
const messages2 = db.iterator({ gt: gt, limit: 100 })
.collect()
.map((e) => e.key);
assert.equal(messages2.length, 2);
assert.equal(messages2[0], messages[messages.length - 2]);
assert.equal(messages2[1], messages[messages.length - 1]);
done();
}));
});
describe('lt & lte', function() {
it('returns one item after head when lt is the head', async((done) => {
const messages = db.iterator({ lt: _.last(items2) })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 1);
assert.equal(messages[0], items2[items2.length - 2]);
done();
}));
it('returns all items when lt is head and limit is -1', async((done) => {
const messages = db.iterator({ lt: _.last(items2), limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, items2.length - 1);
assert.equal(messages[0], items2[0]);
assert.equal(messages[messages.length - 1], items2[items2.length - 2]);
done();
}));
it('returns 3 items when lt is head and limit is 3', async((done) => {
const messages = db.iterator({ lt: _.last(items2), limit: 3 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 3);
assert.equal(messages[0], items2[items2.length - 4]);
assert.equal(messages[2], items2[items2.length - 2]);
done();
}));
it('returns null when lt is the root item', async((done) => {
const messages = db.iterator({ lt: items2[0] }).collect();
assert.equal(messages.length, 0);
done();
}));
it('returns one item when lte is the root item', async((done) => {
const messages = db.iterator({ lte: items2[0] })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 1);
assert.equal(messages[0], items2[0]);
done();
}));
it('returns all items when lte is the head', async((done) => {
const messages = db.iterator({ lte: _.last(items2), limit: -1 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, itemCount);
assert.equal(messages[0], items2[0]);
assert.equal(messages[4], _.last(items2));
done();
}));
it('returns 3 items when lte is the head', async((done) => {
const messages = db.iterator({ lte: _.last(items2), limit: 3 })
.collect()
.map((e) => e.key);
assert.equal(messages.length, 3);
assert.equal(messages[0], items2[items2.length - 3]);
assert.equal(messages[1], items2[items2.length - 2]);
assert.equal(messages[2], _.last(items2));
done();
}));
});
});
});
describe('Delete', function() {
it('deletes a channel from the database', async((done) => {
const result = db.delete();
assert.equal(result, true);
const iter = db.iterator();
assert.equal(iter.next().value, null);
done();
}));
});
describe('Key-Value Store', function() {
before(async((done) => {
db.delete();
done();
}));
it('put', async((done) => {
db.put('key1', 'hello!');
let all = db.iterator().collect();
assert.equal(all.length, 1);
assert.equal(all[0].hash.startsWith('Qm'), true);
assert.equal(all[0].key, 'key1');
// assert.equal(all[0].op, 'PUT');
assert.notEqual(all[0].meta, null);
done();
}));
it('get', async((done) => {
db.put('key1', 'hello!');
const value = db.get('key1');
assert.equal(value, 'hello!');
done();
}));
it('put updates a value', async((done) => {
db.put('key1', 'hello!');
db.put('key1', 'hello again');
const value = db.get('key1');
assert.equal(value, 'hello again');
done();
}));
it('deletes a key', async((done) => {
db.put('key1', 'hello!');
db.del('key1');
const value = db.get('key1');
assert.equal(value, null);
done();
}));
it('deletes a key after multiple updates', async((done) => {
db.put('key1', 'hello1');
db.put('key1', 'hello2');
db.put('key1', 'hello3');
db.del('key1');
const value = db.get('key1');
assert.equal(value, null);
done();
}));
it('put - multiple keys', async((done) => {
db.put('key1', 'hello1');
db.put('key2', 'hello2');
db.put('key3', 'hello3');
const all = db.iterator().collect();
assert.equal(all.length, 1);
done();
}));
it('get - multiple keys', async((done) => {
db.put('key1', 'hello1');
db.put('key2', 'hello2');
db.put('key3', 'hello3');
const v1 = db.get('key1');
const v2 = db.get('key2');
const v3 = db.get('key3');
assert.equal(v1, 'hello1');
assert.equal(v2, 'hello2');
assert.equal(v3, 'hello3');
done();
}));
it('get - integer value', async((done) => {
db.put('key1', 123);
const v1 = db.get('key1');
assert.equal(v1, 123);
done();
}));
it('get - object value', async((done) => {
const val = { one: 'first', two: 2 };
db.put('key1', val);
const v1 = db.get('key1');
assert.equal(_.isEqual(v1, val), true);
done();
}));
it('get - array value', async((done) => {
const val = [1, 2, 3, 4, 5];
db.put('key1', val);
const v1 = db.get('key1');
assert.equal(_.isEqual(v1, val), true);
done();
}));
});
/*
describe('Modes', function() {
var password = 'hello';
it('sets read mode', async((done) => {
try {
var mode = {
mode: "+r",
params: {
password: password
}
};
var modes = db.setMode(mode)
assert.notEqual(modes.r, null);
assert.equal(modes.r.password, password);
} catch(e) {
assert.equal(e, null);
}
done();
}));
it('can\'t read with wrong password', async((done) => {
try {
var modes = orbit.channel(channel, 'invalidpassword').iterator();
assert.equal(true, false);
} catch(e) {
assert.equal(e, 'Unauthorized');
}
done();
}));
it('sets write mode', async((done) => {
try {
var mode = {
mode: "+w",
params: {
ops: [orbit.user.id]
}
};
var modes = orbit.channel(channel, password).setMode(mode);
assert.notEqual(modes.w, null);
assert.equal(modes.w.ops[0], orbit.user.id);
} catch(e) {
assert.equal(e, null);
}
done();
}));
it('can\'t write when user not an op', async((done) => {
// TODO
done();
}));
it('removes write mode', async((done) => {
try {
var modes = orbit.channel(channel, password).setMode({ mode: "-w" });
assert.equal(modes.w, null);
} catch(e) {
assert.equal(e, null);
}
done();
}));
it('removes read mode', async((done) => {
try {
var modes = orbit.channel(channel, password).setMode({ mode: "-r" });
assert.equal(modes.r, null);
} catch(e) {
assert.equal(e, null);
}
done();
}));
});
*/
});