diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..de3e378 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,23 @@ +environment: + matrix: + - nodejs_version: "6" + - nodejs_version: "8" + +# cache: +# - node_modules + +platform: + - x64 + +install: + - ps: Install-Product node $env:nodejs_version $env:platform + - npm install + +test_script: + - node --version + - npm --version + - npm test + +build: off + +version: "{build}" diff --git a/.travis.yml b/.travis.yml index 96adf23..584f308 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,24 +3,26 @@ language: node_js matrix: include: - - node_js: 4 - env: CXX=g++-4.8 - node_js: 6 - env: - - SAUCE=true - - CXX=g++-4.8 - - node_js: stable env: CXX=g++-4.8 + - node_js: 8 + env: CXX=g++-4.8 + # - node_js: stable + # env: CXX=g++-4.8 script: - npm run lint - - npm run flow - - npm test + - npm run test + - npm run coverage + - make test before_script: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start +after_success: + - npm run coverage-publish + addons: firefox: 'latest' apt: diff --git a/circle.yml b/circle.yml index 434211a..d67b6ae 100644 --- a/circle.yml +++ b/circle.yml @@ -2,11 +2,17 @@ machine: node: version: stable +test: + post: + - npm run coverage -- --upload + dependencies: pre: - google-chrome --version - - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' + - curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb + - sudo dpkg -i google-chrome.deb || true - sudo apt-get update - - sudo apt-get --only-upgrade install google-chrome-stable + - sudo apt-get install -f + - sudo apt-get install --only-upgrade lsb-base + - sudo dpkg -i google-chrome.deb - google-chrome --version diff --git a/package.json b/package.json index fb8316a..c99eabf 100644 --- a/package.json +++ b/package.json @@ -4,18 +4,18 @@ "description": "datastore interface", "main": "src/index.js", "scripts": { - "lint": "aegir-lint", - "build": "aegir-build", - "test": "aegir-test", + "lint": "aegir lint", + "build": "aegir build", + "test": "aegir test", "flow": "flow", - "test:node": "aegir-test --env node", - "test:browser": "aegir-test --env browser", - "release": "aegir-release --docs", - "release-minor": "aegir-release --type minor --docs", - "release-major": "aegir-release --type major --docs", - "coverage": "aegir-coverage", - "coverage-publish": "aegir-coverage publish", - "docs": "aegir-docs" + "test:node": "aegir test --target node", + "test:browser": "aegir test --target browser", + "release": "aegir release --docs", + "release-minor": "aegir release --type minor --docs", + "release-major": "aegir release --type major --docs", + "coverage": "aegir coverage", + "coverage-publish": "aegir coverage --provider codecov", + "docs": "aegir docs" }, "repository": { "type": "git", @@ -34,16 +34,16 @@ }, "homepage": "https://github.com/ipfs/interface-datastore#readme", "devDependencies": { - "aegir": "^11.0.2", + "aegir": "^12.1.3", "chai": "^4.1.2", "dirty-chai": "^2.0.1", - "flow-bin": "^0.54.1" + "flow-bin": "^0.58.0" }, "dependencies": { "async": "^2.5.0", "libp2p-crypto": "^0.10.3", "pull-defer": "^0.2.2", - "pull-stream": "^3.6.0", + "pull-stream": "^3.6.1", "uuid": "^3.1.0" }, "engines": { @@ -54,7 +54,8 @@ "David Dias ", "Erin Dachtler ", "Juan Batiz-Benet ", - "dignifiedquire " + "dignifiedquire ", + "Richard Schneider " ], "bundleDependencies": [] -} \ No newline at end of file +} diff --git a/src/key.js b/src/key.js index a97da49..8a1767d 100644 --- a/src/key.js +++ b/src/key.js @@ -1,11 +1,11 @@ /* @flow */ 'use strict' -const path = require('path') const uuid = require('uuid/v4') -const pathSepS = path.sep -const pathSep = new Buffer(pathSepS, 'utf8')[0] +const pathSepS = '/' +const pathSepB = Buffer.from(pathSepS) +const pathSep = pathSepB[0] /** * A Key represents the unique identifier of an object. @@ -28,7 +28,7 @@ class Key { constructor (s /* : string|Buffer */, clean /* : ?bool */) { if (typeof s === 'string') { - this._buf = new Buffer(s) + this._buf = Buffer.from(s) } else if (Buffer.isBuffer(s)) { this._buf = s } @@ -107,17 +107,15 @@ class Key { */ clean () { if (!this._buf || this._buf.length === 0) { - this._buf = new Buffer(pathSepS, 'utf8') + this._buf = Buffer.from(pathSepS) } - this._buf = new Buffer(path.normalize(this.toString())) - if (this._buf[0] !== pathSep) { - this._buf = Buffer.concat([new Buffer(pathSepS, 'utf8'), this._buf]) + this._buf = Buffer.concat([pathSepB, this._buf]) } // normalize does not remove trailing slashes - if (this.toString().length > 1 && this._buf[this._buf.length - 1] === pathSep) { + while (this._buf.length > 1 && this._buf[this._buf.length - 1] === pathSep) { this._buf = this._buf.slice(0, -1) } } @@ -252,7 +250,12 @@ class Key { * */ path () /* : Key */ { - return new Key(this.parent().toString() + pathSepS + this.type()) + let p = this.parent().toString() + if (!p.endsWith(pathSepS)) { + p += pathSepS + } + p += this.type() + return new Key(p) } /** @@ -268,7 +271,7 @@ class Key { parent () /* : Key */ { const list = this.list() if (list.length === 1) { - return new Key(pathSepS, false) + return new Key(pathSepS) } return new Key(list.slice(0, -1).join(pathSepS)) diff --git a/src/tests.js b/src/tests.js index 749c071..452dc9b 100644 --- a/src/tests.js +++ b/src/tests.js @@ -12,10 +12,8 @@ const parallel = require('async/parallel') const map = require('async/map') const each = require('async/each') const crypto = require('libp2p-crypto') -const path = require('path') const Key = require('../src').Key -const n = (p) => path.normalize(p) /* :: import type {Datastore, Callback} from '../src' @@ -59,13 +57,13 @@ module.exports = (test/* : Test */) => { it('simple', (done) => { const k = new Key('/z/one') - check(store).put(k, new Buffer('one'), done) + check(store).put(k, Buffer.from('one'), done) }) it('parallel', (done) => { const data = [] for (let i = 0; i < 100; i++) { - data.push([new Key(`/z/key${i}`), new Buffer(`data${i}`)]) + data.push([new Key(`/z/key${i}`), Buffer.from(`data${i}`)]) } each(data, (d, cb) => { @@ -105,10 +103,10 @@ module.exports = (test/* : Test */) => { it('simple', (done) => { const k = new Key('/z/one') series([ - (cb) => check(store).put(k, new Buffer('hello'), cb), + (cb) => check(store).put(k, Buffer.from('hello'), cb), (cb) => check(store).get(k, (err, res) => { expect(err).to.not.exist() - expect(res).to.be.eql(new Buffer('hello')) + expect(res).to.be.eql(Buffer.from('hello')) cb() }) ], done) @@ -135,10 +133,10 @@ module.exports = (test/* : Test */) => { it('simple', (done) => { const k = new Key('/z/one') series([ - (cb) => check(store).put(k, new Buffer('hello'), cb), + (cb) => check(store).put(k, Buffer.from('hello'), cb), (cb) => check(store).get(k, (err, res) => { expect(err).to.not.exist() - expect(res).to.be.eql(new Buffer('hello')) + expect(res).to.be.eql(Buffer.from('hello')) cb() }), (cb) => check(store).delete(k, cb), @@ -153,7 +151,7 @@ module.exports = (test/* : Test */) => { it('parallel', (done) => { const data = [] for (let i = 0; i < 100; i++) { - data.push([new Key(`/a/key${i}`), new Buffer(`data${i}`)]) + data.push([new Key(`/a/key${i}`), Buffer.from(`data${i}`)]) } series([ @@ -206,11 +204,11 @@ module.exports = (test/* : Test */) => { const b = check(store).batch() series([ - (cb) => check(store).put(new Key('/z/old'), new Buffer('old'), cb), + (cb) => check(store).put(new Key('/z/old'), Buffer.from('old'), cb), (cb) => { - b.put(new Key('/a/one'), new Buffer('1')) - b.put(new Key('/q/two'), new Buffer('2')) - b.put(new Key('/q/three'), new Buffer('3')) + b.put(new Key('/a/one'), Buffer.from('1')) + b.put(new Key('/q/two'), Buffer.from('2')) + b.put(new Key('/q/three'), Buffer.from('3')) b.delete(new Key('/z/old')) b.commit(cb) }, @@ -238,9 +236,9 @@ module.exports = (test/* : Test */) => { series([ (cb) => b.commit(cb), (cb) => parallel([ - (cb) => pull(check(store).query({prefix: n('/a')}), pull.collect(cb)), - (cb) => pull(check(store).query({prefix: n('/z')}), pull.collect(cb)), - (cb) => pull(check(store).query({prefix: n('/q')}), pull.collect(cb)) + (cb) => pull(check(store).query({prefix: '/a'}), pull.collect(cb)), + (cb) => pull(check(store).query({prefix: '/z'}), pull.collect(cb)), + (cb) => pull(check(store).query({prefix: '/q'}), pull.collect(cb)) ], (err, res) => { expect(err).to.not.exist() expect(res[0]).to.have.length(count) @@ -254,9 +252,9 @@ module.exports = (test/* : Test */) => { describe('query', () => { let store - const hello = {key: new Key('/q/1hello'), value: new Buffer('1')} - const world = {key: new Key('/z/2world'), value: new Buffer('2')} - const hello2 = {key: new Key('/z/3hello2'), value: new Buffer('3')} + const hello = {key: new Key('/q/1hello'), value: Buffer.from('1')} + const world = {key: new Key('/z/2world'), value: Buffer.from('2')} + const hello2 = {key: new Key('/z/3hello2'), value: Buffer.from('3')} const filter1 = (entry, cb) => { cb(null, !entry.key.toString().endsWith('hello')) } @@ -290,7 +288,7 @@ module.exports = (test/* : Test */) => { const tests = [ ['empty', {}, [hello, world, hello2]], - ['prefix', {prefix: n('/z')}, [world, hello2]], + ['prefix', {prefix: '/z'}, [world, hello2]], ['1 filter', {filters: [filter1]}, [world, hello2]], ['2 filters', {filters: [filter1, filter2]}, [hello2]], ['limit', {limit: 1}, 1], @@ -329,6 +327,7 @@ module.exports = (test/* : Test */) => { const expected = t[2] if (Array.isArray(expected)) { if (t[1].orders == null) { + expect(res).to.have.length(expected.length) const s = (a, b) => { if (a.key.toString() < b.key.toString()) { return 1 diff --git a/test/key.spec.js b/test/key.spec.js index abcfb1b..c4f454e 100644 --- a/test/key.spec.js +++ b/test/key.spec.js @@ -3,16 +3,14 @@ 'use strict' const expect = require('chai').expect -const path = require('path') const Key = require('../src').Key -const pathSep = path.sep -const n = (p) => path.normalize(p) +const pathSep = '/' describe('Key', () => { const clean = (s) => { - let fixed = n(s) + let fixed = s if (fixed.startsWith(pathSep + pathSep)) { fixed = fixed.slice(1) } @@ -34,7 +32,7 @@ describe('Key', () => { ktype = lnparts.slice(0, -1).join(':') } const kname = lnparts[lnparts.length - 1] - const kchild = clean(fixed + n('/cchildd')) + const kchild = clean(fixed + '/cchildd') const kparent = pathSep + namespaces.slice(0, -1).join(pathSep) const kpath = clean(kparent + pathSep + ktype) const kinstance = fixed + ':inst' @@ -62,35 +60,33 @@ describe('Key', () => { validKey('') validKey('abcde') validKey('disahfidsalfhduisaufidsail') - validKey(n('/fdisahfodisa/fdsa/fdsafdsafdsafdsa/fdsafdsa/')) + validKey('/fdisahfodisa/fdsa/fdsafdsafdsafdsa/fdsafdsa/') validKey('4215432143214321432143214321') - validKey(n('a\\b\\c//d\\')) - validKey(n('/fdisaha////fdsa////fdsafdsafdsafdsa/fdsafdsa/')) + validKey('a/b/c/d/') validKey('abcde:fdsfd') validKey('disahfidsalfhduisaufidsail:fdsa') - validKey(n('/fdisahfodisa/fdsa/fdsafdsafdsafdsa/fdsafdsa/:')) + validKey('/fdisahfodisa/fdsa/fdsafdsafdsafdsa/fdsafdsa/:') validKey('4215432143214321432143214321:') - validKey(n('fdisaha////fdsa////fdsafdsafdsafdsa/fdsafdsa/f:fdaf')) }) it('ancestry', () => { - const k1 = new Key(n('/A/B/C')) - const k2 = new Key(n('/A/B/C/D')) + const k1 = new Key('/A/B/C') + const k2 = new Key('/A/B/C/D') - expect(k1.toString()).to.be.eql(n('/A/B/C')) - expect(k2.toString()).to.be.eql(n('/A/B/C/D')) + expect(k1.toString()).to.be.eql('/A/B/C') + expect(k2.toString()).to.be.eql('/A/B/C/D') const checks = [ k1.isAncestorOf(k2), k2.isDecendantOf(k1), - new Key(n('/A')).isAncestorOf(k2), - new Key(n('/A')).isAncestorOf(k1), - !new Key(n('/A')).isDecendantOf(k2), - !new Key(n('/A')).isDecendantOf(k1), - k2.isDecendantOf(new Key(n('/A'))), - k1.isDecendantOf(new Key(n('/A'))), - !k2.isAncestorOf(new Key(n('/A'))), - !k1.isAncestorOf(new Key(n('/A'))), + new Key('/A').isAncestorOf(k2), + new Key('/A').isAncestorOf(k1), + !new Key('/A').isDecendantOf(k2), + !new Key('/A').isDecendantOf(k1), + k2.isDecendantOf(new Key('/A')), + k1.isDecendantOf(new Key('/A')), + !k2.isAncestorOf(new Key('/A')), + !k1.isAncestorOf(new Key('/A')), !k2.isAncestorOf(k2), !k1.isAncestorOf(k1) ] @@ -103,8 +99,8 @@ describe('Key', () => { }) it('type', () => { - const k1 = new Key(n('/A/B/C:c')) - const k2 = new Key(n('/A/B/C:c/D:d')) + const k1 = new Key('/A/B/C:c') + const k2 = new Key('/A/B/C:c/D:d') expect(k1.isAncestorOf(k2)).to.eql(true) expect(k2.isDecendantOf(k1)).to.eql(true) @@ -116,13 +112,14 @@ describe('Key', () => { it('random', () => { const keys = {} - for (let i = 0; i < 1000; i++) { + const k = 100 + for (let i = 0; i < k; i++) { const r = Key.random() expect(keys).to.not.have.key(r.toString()) keys[r.toString()] = true } - expect(Object.keys(keys)).to.have.length(1000) + expect(Object.keys(keys)).to.have.length(k) }) it('less', () => { @@ -134,12 +131,12 @@ describe('Key', () => { expect(bk.less(ak)).to.eql(false) } - checkLess(n('/a/b/c'), n('/a/b/c/d')) - checkLess(n('/a/b'), n('/a/b/c/d')) - checkLess(n('/a'), n('/a/b/c/d')) - checkLess(n('/a/a/c'), n('/a/b/c')) - checkLess(n('/a/a/d'), n('/a/b/c')) - checkLess(n('/a/b/c/d/e/f/g/h'), n('/b')) - checkLess(pathSep, n('/a')) + checkLess('/a/b/c', '/a/b/c/d') + checkLess('/a/b', '/a/b/c/d') + checkLess('/a', '/a/b/c/d') + checkLess('/a/a/c', '/a/b/c') + checkLess('/a/a/d', '/a/b/c') + checkLess('/a/b/c/d/e/f/g/h', '/b') + checkLess(pathSep, '/a') }) }) diff --git a/test/utils.spec.js b/test/utils.spec.js index 120ddc7..807ae79 100644 --- a/test/utils.spec.js +++ b/test/utils.spec.js @@ -84,4 +84,8 @@ describe('utils', () => { 'helloworld' ) }) + + it('provides a temp folder', () => { + expect(utils.tmpdir()).to.not.equal('') + }) })