Merge branch 'master' into determine-address

This commit is contained in:
Tyler Yasaka 2018-12-06 11:20:46 -08:00
commit 15aae2959b
No known key found for this signature in database
GPG Key ID: D3EC8FC9F3B711F4
14 changed files with 514 additions and 319 deletions

2
API.md
View File

@ -76,6 +76,8 @@ Creates and returns an instance of OrbitDB. Use the optional `directory` argumen
- `keystore` (Keystore Instance) : By default creates an instance of [Keystore](https://github.com/orbitdb/orbit-db-keystore). A custom keystore instance can be used, see [this](https://github.com/orbitdb/orbit-db/blob/master/test/utils/custom-test-keystore.js) for an example.
- 'cache' (Cache Instance) : By default creates an instance of [Cache](https://github.com/orbitdb/orbit-db-cache). A custom cache instance can also be used.
After creating an `OrbitDB` instance , you can access the different data stores. Creating a database instance, eg. with `orbitdb.keyvalue(...)`, returns a *Promise* that resolves to a [database instance](#store-api). See the [Store](#store-api) section for details of common methods and properties.
*For further details, see usage for [kvstore](https://github.com/orbitdb/orbit-db-kvstore#usage), [eventlog](https://github.com/orbitdb/orbit-db-eventstore#usage), [feed](https://github.com/orbitdb/orbit-db-feedstore#usage), [docstore](https://github.com/orbitdb/orbit-db-docstore#usage) and [counter](https://github.com/orbitdb/orbit-db-counterstore#usage).*

71
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,71 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [community@orbitdb.org](mailto:community@orbitdb.org), which goes to all members of the @OrbitDB community team, or to [richardlitt@orbitdb.org](mailto:richardlitt@orbitdb.org), which goes only to [@RichardLitt](https://github.com/RichardLitt) or to [haadcode@orbitdb.org](mailto:haadcode@orbitdb.org), which goes only to [@haadcode](https://github.com/haadcode).
All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org

View File

@ -20,6 +20,10 @@ build: test
clean:
rm -rf orbitdb/
rm -rf node_modules/
rm package-lock.json
clean-dependencies: clean
if [ -a package-lock.json ]; then rm package-lock.json; fi;
rebuild: | clean-dependencies build
.PHONY: test build

View File

@ -27,6 +27,9 @@ All databases are [implemented](https://github.com/orbitdb/orbit-db-store) on to
#### Project status & support
This is the Javascript implementation and it works both in **Browsers** and **Node.js** with support for Linux and OS X (Windows is not supported yet). The minimum required version of Node.js is now 8.0.0. To use with older versions of Node.js, we provide an ES5-compatible build through the npm package, located in `dist/es5/` when installed through npm.
#### Community Calls
We also have **regular community calls**, which we announce in the issues in [the @orbitdb welcome repository](https://github.com/orbitdb/welcome/issues). Join us!
## Table of Contents
<!-- toc -->
@ -257,6 +260,8 @@ We also have **regular community calls**, which we announce in the issues in [th
If you want to code but don't know where to start, check out the issues labelled ["help wanted"](https://github.com/orbitdb/orbit-db/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+sort%3Areactions-%2B1-desc) or the project's [status board](https://waffle.io/orbitdb/orbit-db).
Please note that we have a [Code of Conduct](CODE_OF_CONDUCT.md), and that all activity in the [@orbitdb](https://github.com/orbitdb) organization falls under it. Read it when you get the chance, as being part of this community means that you agree to abide by it. Thanks.
## Sponsors
The development of OrbitDB has been sponsored by:

68
package-lock.json generated
View File

@ -272,6 +272,11 @@
}
}
},
"argsarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/argsarray/-/argsarray-0.0.1.tgz",
"integrity": "sha1-bnIHtOzbObCviDA/pa4ivajfYcs="
},
"arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@ -2270,6 +2275,11 @@
"es5-ext": "0.10.45"
}
},
"d64": {
"version": "1.0.0",
"resolved": "http://registry.npmjs.org/d64/-/d64-1.0.0.tgz",
"integrity": "sha1-QAKofoUMv8n52XBrYPymE6MzbpA="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@ -5236,6 +5246,11 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"has-localstorage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-localstorage/-/has-localstorage-1.0.1.tgz",
"integrity": "sha1-/mJAbEdn+9bXhNrGkFkoEIuClxs="
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@ -5414,6 +5429,15 @@
"promisify-es6": "1.0.3"
}
},
"humble-localstorage": {
"version": "1.4.2",
"resolved": "http://registry.npmjs.org/humble-localstorage/-/humble-localstorage-1.4.2.tgz",
"integrity": "sha1-0Fqw1SbE7b3b98amDfb/WAUoNGk=",
"requires": {
"has-localstorage": "1.0.1",
"localstorage-memory": "1.0.3"
}
},
"idb-readable-stream": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/idb-readable-stream/-/idb-readable-stream-0.0.4.tgz",
@ -8809,6 +8833,45 @@
"json5": "0.5.1"
}
},
"localstorage-down": {
"version": "0.6.7",
"resolved": "https://registry.npmjs.org/localstorage-down/-/localstorage-down-0.6.7.tgz",
"integrity": "sha1-0Hmak7MebF+lGI7AYkLrHM6dbRU=",
"requires": {
"abstract-leveldown": "0.12.3",
"argsarray": "0.0.1",
"buffer-from": "0.1.2",
"d64": "1.0.0",
"humble-localstorage": "1.4.2",
"inherits": "2.0.3",
"tiny-queue": "0.2.0"
},
"dependencies": {
"abstract-leveldown": {
"version": "0.12.3",
"resolved": "http://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-0.12.3.tgz",
"integrity": "sha1-EWsexcdxDvei1XBnaLvbREC+EHA=",
"requires": {
"xtend": "3.0.0"
}
},
"buffer-from": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
},
"xtend": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz",
"integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo="
}
}
},
"localstorage-memory": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/localstorage-memory/-/localstorage-memory-1.0.3.tgz",
"integrity": "sha512-t9P8WB6DcVttbw/W4PIE8HOqum8Qlvx5SjR6oInwR9Uia0EEmyUeBh7S+weKByW+l/f45Bj4L/dgZikGFDM6ng=="
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
@ -12996,6 +13059,11 @@
"integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=",
"dev": true
},
"tiny-queue": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.0.tgz",
"integrity": "sha1-xJ/LXIdVW+G0pd9+uHEB1beLydw="
},
"to-array": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",

View File

@ -15,6 +15,7 @@
"dependencies": {
"ipfs-pubsub-1on1": "~0.0.4",
"ipld-dag-pb": "0.14.11",
"localstorage-down": "^0.6.7",
"logplease": "^1.2.14",
"multihashes": "^0.4.12",
"orbit-db-cache": "~0.2.4",

View File

@ -37,6 +37,7 @@ class OrbitDB {
this.stores = {}
this.directory = directory || './orbitdb'
this.keystore = options.keystore || Keystore.create(path.join(this.directory, this.id, '/keystore'))
this.cache = options.cache || Cache
this.key = this.keystore.getKey(this.id) || this.keystore.createKey(this.id)
this._directConnections = {}
}
@ -357,7 +358,7 @@ class OrbitDB {
async _loadCache (directory, dbAddress) {
let cache
try {
cache = await Cache.load(directory, dbAddress)
cache = await this.cache.load(directory, dbAddress)
} catch (e) {
console.log(e)
logger.error("Couldn't load Cache:", e)

58
test/custom-cache.test.js Normal file
View File

@ -0,0 +1,58 @@
'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,
databases,
} = require('./utils')
const dbPath = './orbitdb/tests/customKeystore'
const ipfsPath = './orbitdb/tests/customKeystore/ipfs'
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()
})
})
})
})
})

View File

@ -10,54 +10,12 @@ const {
stopIpfs,
testAPIs,
CustomTestKeystore,
databases,
} = 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 Keystore (${API})`, function() {
this.timeout(20000)

View File

@ -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()
})
})
})
})

View File

@ -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)

44
test/utils/databases.js Normal file
View File

@ -0,0 +1,44 @@
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,
},
]
module.exports = databases

View File

@ -6,3 +6,5 @@ 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')
exports.databases = require('./databases')

View File

@ -5,59 +5,17 @@ const rmrf = require('rimraf')
const OrbitDB = require('../src/OrbitDB')
// Include test utilities
const {
config,
startIpfs,
stopIpfs,
testAPIs,
const {
config,
startIpfs,
stopIpfs,
testAPIs,
databases,
} = require('./utils')
const dbPath = './orbitdb/tests/write-permissions'
const ipfsPath = './orbitdb/tests/write-permissions/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 - Write Permissions (${API})`, function() {
this.timeout(20000)
@ -75,10 +33,10 @@ Object.keys(testAPIs).forEach(API => {
})
after(async () => {
if(orbitdb1)
if(orbitdb1)
await orbitdb1.stop()
if(orbitdb2)
if(orbitdb2)
await orbitdb2.stop()
if (ipfsd)
@ -88,10 +46,10 @@ Object.keys(testAPIs).forEach(API => {
describe('allows multiple peers to write to the databases', function() {
databases.forEach(async (database) => {
it(database.type + ' allows multiple writers', async () => {
let options = {
let options = {
// Set write access for both clients
write: [
orbitdb1.key.getPublic('hex'),
orbitdb1.key.getPublic('hex'),
orbitdb2.key.getPublic('hex')
],
}
@ -115,10 +73,10 @@ Object.keys(testAPIs).forEach(API => {
describe('syncs databases', function() {
databases.forEach(async (database) => {
it(database.type + ' syncs', async () => {
let options = {
let options = {
// Set write access for both clients
write: [
orbitdb1.key.getPublic('hex'),
orbitdb1.key.getPublic('hex'),
orbitdb2.key.getPublic('hex')
],
}
@ -148,7 +106,7 @@ Object.keys(testAPIs).forEach(API => {
describe('syncs databases that anyone can write to', function() {
databases.forEach(async (database) => {
it(database.type + ' syncs', async () => {
let options = {
let options = {
// Set write permission for everyone
write: ['*'],
}
@ -179,7 +137,7 @@ Object.keys(testAPIs).forEach(API => {
databases.forEach(async (database) => {
it(database.type + ' doesn\'t sync', async () => {
let options = {
let options = {
// Only peer 1 can write
write: [orbitdb1.key.getPublic('hex')],
}
@ -228,7 +186,7 @@ Object.keys(testAPIs).forEach(API => {
describe('throws an error if peer is not allowed to write to the database', function() {
databases.forEach(async (database) => {
it(database.type + ' throws an error', async () => {
let options = {
let options = {
// No write access (only creator of the database can write)
write: [],
}