From 5797641fbabd89fe1b5c8ecb6a79633c2c964a53 Mon Sep 17 00:00:00 2001 From: Zach Ferland Date: Fri, 30 Nov 2018 16:40:19 -0500 Subject: [PATCH] test: add custom test cache, add persistence test against custom cache, add store tests against cache --- package.json | 1 + test/custom-cache.test.js | 100 +++++++ test/persistency.js | 448 ++++++++++++++++---------------- test/utils/custom-test-cache.js | 9 + test/utils/index.js | 1 + 5 files changed, 342 insertions(+), 217 deletions(-) create mode 100644 test/custom-cache.test.js create mode 100644 test/utils/custom-test-cache.js diff --git a/package.json b/package.json index 1953579..04534e3 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "main": "src/OrbitDB.js", "dependencies": { "ipfs-pubsub-1on1": "~0.0.4", + "localstorage-down": "^0.6.7", "logplease": "^1.2.14", "multihashes": "^0.4.12", "orbit-db-cache": "~0.2.4", diff --git a/test/custom-cache.test.js b/test/custom-cache.test.js new file mode 100644 index 0000000..9cb7f43 --- /dev/null +++ b/test/custom-cache.test.js @@ -0,0 +1,100 @@ +'use strict' + +const assert = require('assert') +const rmrf = require('rimraf') +const OrbitDB = require('../src/OrbitDB') +const CustomCache = require('orbit-db-cache') +// Include test utilities +const { + config, + startIpfs, + stopIpfs, + testAPIs, + CustomTestCache +} = require('./utils') + +const dbPath = './orbitdb/tests/customKeystore' +const ipfsPath = './orbitdb/tests/customKeystore/ipfs' + +const databases = [ + { + type: 'eventlog', + create: (orbitdb, name, options) => orbitdb.eventlog(name, options), + tryInsert: (db) => db.add('hello'), + query: (db) => db.iterator({ limit: -1 }).collect(), + getTestValue: (db) => db.iterator({ limit: -1 }).collect()[0].payload.value, + expectedValue: 'hello', + }, + { + type: 'feed', + create: (orbitdb, name, options) => orbitdb.feed(name, options), + tryInsert: (db) => db.add('hello'), + query: (db) => db.iterator({ limit: -1 }).collect(), + getTestValue: (db) => db.iterator({ limit: -1 }).collect()[0].payload.value, + expectedValue: 'hello', + }, + { + type: 'key-value', + create: (orbitdb, name, options) => orbitdb.kvstore(name, options), + tryInsert: (db) => db.set('one', 'hello'), + query: (db) => [], + getTestValue: (db) => db.get('one'), + expectedValue: 'hello', + }, + { + type: 'documents', + create: (orbitdb, name, options) => orbitdb.docstore(name, options), + tryInsert: (db) => db.put({ _id: 'hello world', doc: 'all the things'}), + query: (db) => [], + getTestValue: (db) => db.get('hello world'), + expectedValue: [{ _id: 'hello world', doc: 'all the things'}], + }, + { + type: 'counter', + create: (orbitdb, name, options) => orbitdb.counter(name, options), + tryInsert: (db) => db.inc(8), + query: (db) => [], + getTestValue: (db) => db.value, + expectedValue: 8, + }, +] + +Object.keys(testAPIs).forEach(API => { + describe(`orbit-db - Use a Custom Cache (${API})`, function() { + this.timeout(20000) + + let ipfsd, ipfs, orbitdb1 + + before(async () => { + config.daemon1.repo = ipfsPath + rmrf.sync(config.daemon1.repo) + rmrf.sync(dbPath) + ipfsd = await startIpfs(API, config.daemon1) + ipfs = ipfsd.api + orbitdb1 = new OrbitDB(ipfs, dbPath + '/1', { + cache: CustomTestCache + }) + }) + + after(async () => { + if(orbitdb1) + await orbitdb1.stop() + + if (ipfsd) + await stopIpfs(ipfsd) + }) + + describe('allows orbit to use a custom cache with different store types', function() { + databases.forEach(async (database) => { + it(database.type + ' allows custom keystore', async () => { + const db1 = await database.create(orbitdb1, 'custom-keystore') + await database.tryInsert(db1) + + assert.deepEqual(database.getTestValue(db1), database.expectedValue) + + await db1.close() + }) + }) + }) + }) +}) diff --git a/test/persistency.js b/test/persistency.js index 159a15b..5f264d0 100644 --- a/test/persistency.js +++ b/test/persistency.js @@ -11,265 +11,279 @@ const { startIpfs, stopIpfs, testAPIs, + CustomTestCache } = require('./utils') const dbPath = './orbitdb/tests/persistency' const ipfsPath = './orbitdb/tests/persistency/ipfs' +const tests = [ + { + title: 'Persistency', + orbitDBConfig: {} + }, + { + title: 'Persistency with custom cache', + orbitDBConfig: { cache: CustomTestCache } + } +] + Object.keys(testAPIs).forEach(API => { - describe(`orbit-db - Persistency (${API})`, function() { - this.timeout(config.timeout) + tests.forEach(test => { + describe(`orbit-db - ${test.title} (${API})`, function() { + this.timeout(config.timeout) - const entryCount = 65 + const entryCount = 65 - let ipfsd, ipfs, orbitdb1, db, address + let ipfsd, ipfs, orbitdb1, db, address - before(async () => { - config.daemon1.repo = ipfsPath - rmrf.sync(config.daemon1.repo) - rmrf.sync(dbPath) - ipfsd = await startIpfs(API, config.daemon1) - ipfs = ipfsd.api - orbitdb1 = new OrbitDB(ipfs, dbPath + '/1') - }) - - after(async () => { - if(orbitdb1) - await orbitdb1.stop() - - if (ipfsd) - await stopIpfs(ipfsd) - }) - - describe('load', function() { - beforeEach(async () => { - const dbName = new Date().getTime().toString() - const entryArr = [] - - for (let i = 0; i < entryCount; i ++) - entryArr.push(i) - - db = await orbitdb1.eventlog(dbName) - address = db.address.toString() - await mapSeries(entryArr, (i) => db.add('hello' + i)) - await db.close() - db = null + before(async () => { + config.daemon1.repo = ipfsPath + rmrf.sync(config.daemon1.repo) + rmrf.sync(dbPath) + ipfsd = await startIpfs(API, config.daemon1) + ipfs = ipfsd.api + orbitdb1 = new OrbitDB(ipfs, dbPath + '/1', test.orbitDBConfig) }) - afterEach(async () => { - await db.drop() + after(async () => { + if(orbitdb1) + await orbitdb1.stop() + + if (ipfsd) + await stopIpfs(ipfsd) }) - it('loads database from local cache', async () => { - db = await orbitdb1.eventlog(address) - await db.load() - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, entryCount) - assert.equal(items[0].payload.value, 'hello0') - assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) - }) + describe('load', function() { + beforeEach(async () => { + const dbName = new Date().getTime().toString() + const entryArr = [] - it('loads database partially', async () => { - const amount = 33 - db = await orbitdb1.eventlog(address) - await db.load(amount) - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, amount) - assert.equal(items[0].payload.value, 'hello' + (entryCount - amount)) - assert.equal(items[1].payload.value, 'hello' + (entryCount - amount + 1)) - assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) - }) + for (let i = 0; i < entryCount; i ++) + entryArr.push(i) - it('load and close several times', async () => { - const amount = 8 - for (let i = 0; i < amount; i ++) { + db = await orbitdb1.eventlog(dbName) + address = db.address.toString() + await mapSeries(entryArr, (i) => db.add('hello' + i)) + await db.close() + db = null + }) + + afterEach(async () => { + await db.drop() + }) + + it('loads database from local cache', async () => { db = await orbitdb1.eventlog(address) await db.load() const items = db.iterator({ limit: -1 }).collect() assert.equal(items.length, entryCount) assert.equal(items[0].payload.value, 'hello0') - assert.equal(items[1].payload.value, 'hello1') assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) - await db.close() - } - }) + }) - it('closes database while loading', async () => { - db = await orbitdb1.eventlog(address) - db.load() // don't wait for load to finish - await db.close() - assert.equal(db._cache.store, null) - }) - - it('load, add one, close - several times', async () => { - const amount = 8 - for (let i = 0; i < amount; i ++) { + it('loads database partially', async () => { + const amount = 33 db = await orbitdb1.eventlog(address) - await db.load() - await db.add('hello' + (entryCount + i)) + await db.load(amount) const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, entryCount + i + 1) - assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount + i)) - await db.close() - } - }) + assert.equal(items.length, amount) + assert.equal(items[0].payload.value, 'hello' + (entryCount - amount)) + assert.equal(items[1].payload.value, 'hello' + (entryCount - amount + 1)) + assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) + }) - it('loading a database emits \'ready\' event', async () => { - db = await orbitdb1.eventlog(address) - return new Promise(async (resolve) => { - db.events.on('ready', () => { + it('load and close several times', async () => { + const amount = 8 + for (let i = 0; i < amount; i ++) { + db = await orbitdb1.eventlog(address) + await db.load() const items = db.iterator({ limit: -1 }).collect() assert.equal(items.length, entryCount) assert.equal(items[0].payload.value, 'hello0') + assert.equal(items[1].payload.value, 'hello1') assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) - resolve() - }) - await db.load() + await db.close() + } }) - }) - it('loading a database emits \'load.progress\' event', async () => { - db = await orbitdb1.eventlog(address) - return new Promise(async (resolve, reject) => { - let count = 0 - db.events.on('load.progress', (address, hash, entry) => { - count ++ - try { - assert.equal(address, db.address.toString()) - - const { progress, max } = db.replicationStatus - assert.equal(max, entryCount) - assert.equal(progress, count) - - assert.notEqual(hash, null) - assert.notEqual(entry, null) - - if (progress === entryCount && count === entryCount) { - setTimeout(() => { - resolve() - }, 200) - } - } catch (e) { - reject(e) - } - }) - // Start loading the database - await db.load() - }) - }) - }) - - describe('load from empty snapshot', function() { - it('loads database from an empty snapshot', async () => { - db = await orbitdb1.eventlog('empty-snapshot') - address = db.address.toString() - await db.saveSnapshot() - await db.close() - - db = await orbitdb1.open(address) - await db.loadFromSnapshot() - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, 0) - }) - }) - - describe('load from snapshot', function() { - beforeEach(async () => { - const dbName = new Date().getTime().toString() - const entryArr = [] - - for (let i = 0; i < entryCount; i ++) - entryArr.push(i) - - db = await orbitdb1.eventlog(dbName) - address = db.address.toString() - await mapSeries(entryArr, (i) => db.add('hello' + i)) - await db.saveSnapshot() - await db.close() - db = null - }) - - afterEach(async () => { - await db.drop() - }) - - it('loads database from snapshot', async () => { - db = await orbitdb1.eventlog(address) - await db.loadFromSnapshot() - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, entryCount) - assert.equal(items[0].payload.value, 'hello0') - assert.equal(items[entryCount - 1].payload.value, 'hello' + (entryCount - 1)) - }) - - it('load, add one and save snapshot several times', async () => { - const amount = 4 - for (let i = 0; i < amount; i ++) { + it('closes database while loading', async () => { db = await orbitdb1.eventlog(address) - await db.loadFromSnapshot() - await db.add('hello' + (entryCount + i)) - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, entryCount + i + 1) - assert.equal(items[0].payload.value, 'hello0') - assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount + i)) + db.load() // don't wait for load to finish + await db.close() + assert.equal(db._cache.store, null) + }) + + it('load, add one, close - several times', async () => { + const amount = 8 + for (let i = 0; i < amount; i ++) { + db = await orbitdb1.eventlog(address) + await db.load() + await db.add('hello' + (entryCount + i)) + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, entryCount + i + 1) + assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount + i)) + await db.close() + } + }) + + it('loading a database emits \'ready\' event', async () => { + db = await orbitdb1.eventlog(address) + return new Promise(async (resolve) => { + db.events.on('ready', () => { + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, entryCount) + assert.equal(items[0].payload.value, 'hello0') + assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount - 1)) + resolve() + }) + await db.load() + }) + }) + + it('loading a database emits \'load.progress\' event', async () => { + db = await orbitdb1.eventlog(address) + return new Promise(async (resolve, reject) => { + let count = 0 + db.events.on('load.progress', (address, hash, entry) => { + count ++ + try { + assert.equal(address, db.address.toString()) + + const { progress, max } = db.replicationStatus + assert.equal(max, entryCount) + assert.equal(progress, count) + + assert.notEqual(hash, null) + assert.notEqual(entry, null) + + if (progress === entryCount && count === entryCount) { + setTimeout(() => { + resolve() + }, 200) + } + } catch (e) { + reject(e) + } + }) + // Start loading the database + await db.load() + }) + }) + }) + + describe('load from empty snapshot', function() { + it('loads database from an empty snapshot', async () => { + db = await orbitdb1.eventlog('empty-snapshot') + address = db.address.toString() await db.saveSnapshot() await db.close() - } - }) - it('throws an error when trying to load a missing snapshot', async () => { - db = await orbitdb1.eventlog(address) - await db.drop() - db = null - db = await orbitdb1.eventlog(address) - - let err - try { - await db.loadFromSnapshot() - } catch (e) { - err = e.toString() - } - assert.equal(err, `Error: Snapshot for ${address} not found!`) - }) - - it('loading a database emits \'ready\' event', async () => { - db = await orbitdb1.eventlog(address) - return new Promise(async (resolve) => { - db.events.on('ready', () => { - const items = db.iterator({ limit: -1 }).collect() - assert.equal(items.length, entryCount) - assert.equal(items[0].payload.value, 'hello0') - assert.equal(items[entryCount - 1].payload.value, 'hello' + (entryCount - 1)) - resolve() - }) + db = await orbitdb1.open(address) await db.loadFromSnapshot() + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, 0) }) }) - it('loading a database emits \'load.progress\' event', async () => { - db = await orbitdb1.eventlog(address) - return new Promise(async (resolve, reject) => { - let count = 0 - db.events.on('load.progress', (address, hash, entry) => { - count ++ - try { - assert.equal(address, db.address.toString()) + describe('load from snapshot', function() { + beforeEach(async () => { + const dbName = new Date().getTime().toString() + const entryArr = [] - const { progress, max } = db.replicationStatus - assert.equal(max, entryCount) - assert.equal(progress, count) + for (let i = 0; i < entryCount; i ++) + entryArr.push(i) - assert.notEqual(hash, null) - assert.notEqual(entry, null) - if (progress === entryCount && count === entryCount) { - resolve() - } - } catch (e) { - reject(e) - } - }) - // Start loading the database + db = await orbitdb1.eventlog(dbName) + address = db.address.toString() + await mapSeries(entryArr, (i) => db.add('hello' + i)) + await db.saveSnapshot() + await db.close() + db = null + }) + + afterEach(async () => { + await db.drop() + }) + + it('loads database from snapshot', async () => { + db = await orbitdb1.eventlog(address) await db.loadFromSnapshot() + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, entryCount) + assert.equal(items[0].payload.value, 'hello0') + assert.equal(items[entryCount - 1].payload.value, 'hello' + (entryCount - 1)) + }) + + it('load, add one and save snapshot several times', async () => { + const amount = 4 + for (let i = 0; i < amount; i ++) { + db = await orbitdb1.eventlog(address) + await db.loadFromSnapshot() + await db.add('hello' + (entryCount + i)) + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, entryCount + i + 1) + assert.equal(items[0].payload.value, 'hello0') + assert.equal(items[items.length - 1].payload.value, 'hello' + (entryCount + i)) + await db.saveSnapshot() + await db.close() + } + }) + + it('throws an error when trying to load a missing snapshot', async () => { + db = await orbitdb1.eventlog(address) + await db.drop() + db = null + db = await orbitdb1.eventlog(address) + + let err + try { + await db.loadFromSnapshot() + } catch (e) { + err = e.toString() + } + assert.equal(err, `Error: Snapshot for ${address} not found!`) + }) + + it('loading a database emits \'ready\' event', async () => { + db = await orbitdb1.eventlog(address) + return new Promise(async (resolve) => { + db.events.on('ready', () => { + const items = db.iterator({ limit: -1 }).collect() + assert.equal(items.length, entryCount) + assert.equal(items[0].payload.value, 'hello0') + assert.equal(items[entryCount - 1].payload.value, 'hello' + (entryCount - 1)) + resolve() + }) + await db.loadFromSnapshot() + }) + }) + + it('loading a database emits \'load.progress\' event', async () => { + db = await orbitdb1.eventlog(address) + return new Promise(async (resolve, reject) => { + let count = 0 + db.events.on('load.progress', (address, hash, entry) => { + count ++ + try { + assert.equal(address, db.address.toString()) + + const { progress, max } = db.replicationStatus + assert.equal(max, entryCount) + assert.equal(progress, count) + + assert.notEqual(hash, null) + assert.notEqual(entry, null) + if (progress === entryCount && count === entryCount) { + resolve() + } + } catch (e) { + reject(e) + } + }) + // Start loading the database + await db.loadFromSnapshot() + }) }) }) }) diff --git a/test/utils/custom-test-cache.js b/test/utils/custom-test-cache.js new file mode 100644 index 0000000..cd7b1eb --- /dev/null +++ b/test/utils/custom-test-cache.js @@ -0,0 +1,9 @@ +const OrbitDbCache = require('orbit-db-cache/Cache.js') +const localdown = require('localstorage-down') + +/** + * A custom cache example. To create a differing custom example, orbitdb cache was + * used with another abstract-leveldown compliant storage, localdown as an example + */ + +module.exports = OrbitDbCache(localdown) diff --git a/test/utils/index.js b/test/utils/index.js index 3af6322..330e801 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -6,3 +6,4 @@ exports.waitForPeers = require('./wait-for-peers') exports.connectPeers = require('./connect-peers') exports.MemStore = require('./mem-store') exports.CustomTestKeystore = require('./custom-test-keystore') +exports.CustomTestCache = require('./custom-test-cache')