diff --git a/.airtap.yml b/.airtap.yml index fc87a0c4..35548f0e 100644 --- a/.airtap.yml +++ b/.airtap.yml @@ -1,13 +1,19 @@ +providers: + - airtap-sauce + - airtap-default + browsers: - name: chrome - version: latest - platform: Windows 10 - name: firefox - version: latest - platform: Windows 10 - - name: iphone - version: '9.0' - - name: android - version: '6.0' - - name: microsoftedge - version: latest + - name: safari + version: 12..latest + - name: ios_saf + version: 12..latest + - name: chrome for android + version: 6..latest + - name: msedge + +presets: + local: + browsers: + - name: default \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 24230321..35c47561 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,9 +5,4 @@ updates: schedule: interval: monthly ignore: - - dependency-name: buffer - dependency-name: dependency-check - - dependency-name: sinon - - dependency-name: airtap - - dependency-name: nyc - - dependency-name: standard diff --git a/.travis.yml b/.travis.yml index a81ab914..38bc1a29 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,16 +4,15 @@ language: node_js matrix: fast_finish: true include: - - node_js: 6 + - node_js: 10 env: CMD=test - - node_js: 8 + - node_js: 12 env: CMD=test - - node_js: 10 + - node_js: 14 env: CMD=test - node_js: stable env: CMD=test-browsers addons: - sauce_connect: true hosts: - airtap.local diff --git a/README.md b/README.md index 9f01066d..ae5595a6 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ FakeLevelDOWN.prototype._open = function (options, callback) { this._store = {} // Use nextTick to be a nice async citizen - process.nextTick(callback) + this._nextTick(callback) } FakeLevelDOWN.prototype._serializeKey = function (key) { @@ -125,7 +125,7 @@ FakeLevelDOWN.prototype._serializeKey = function (key) { FakeLevelDOWN.prototype._put = function (key, value, options, callback) { this._store[key] = value - process.nextTick(callback) + this._nextTick(callback) } FakeLevelDOWN.prototype._get = function (key, options, callback) { @@ -133,15 +133,15 @@ FakeLevelDOWN.prototype._get = function (key, options, callback) { if (value === undefined) { // 'NotFound' error, consistent with LevelDOWN API - return process.nextTick(callback, new Error('NotFound')) + return this._nextTick(callback, new Error('NotFound')) } - process.nextTick(callback, null, value) + this._nextTick(callback, null, value) } FakeLevelDOWN.prototype._del = function (key, options, callback) { delete this._store[key] - process.nextTick(callback) + this._nextTick(callback) } ``` @@ -167,7 +167,7 @@ See [`memdown`](https://github.com/Level/memdown/) if you are looking for a comp ## Browser Support -[![Sauce Test Status](https://saucelabs.com/browser-matrix/abstract-leveldown.svg)](https://saucelabs.com/u/abstract-leveldown) +[![Sauce Test Status](https://app.saucelabs.com/browser-matrix/abstract-leveldown.svg)](https://app.saucelabs.com/u/abstract-leveldown) ## Public API For Consumers @@ -251,11 +251,6 @@ Returns an [`iterator`](#iterator). Accepts the following range options: - `reverse` _(boolean, default: `false`)_: iterate entries in reverse order. Beware that a reverse seek can be slower than a forward seek. - `limit` _(number, default: `-1`)_: limit the number of entries collected by this iterator. This number represents a _maximum_ number of entries and may not be reached if you get to the end of the range first. A value of `-1` means there is no limit. When `reverse=true` the entries with the highest keys will be returned instead of the lowest keys. -Legacy options: - -- `start`: instead use `gte` -- `end`: instead use `lte`. - **Note** Zero-length strings, buffers and arrays as well as `null` and `undefined` are invalid as keys, yet valid as range options. These types are significant in encodings like [`bytewise`](https://github.com/deanlandolt/bytewise) and [`charwise`](https://github.com/dominictarr/charwise) as well as some underlying stores like IndexedDB. Consumers of an implementation should assume that `{ gt: undefined }` is _not_ the same as `{}`. An implementation can choose to: - [_Serialize_](#db_serializekeykey) or [_encode_][encoding-down] these types to make them meaningful @@ -288,13 +283,13 @@ If no options are provided, all entries will be deleted. The `callback` function ### `chainedBatch` -#### `chainedBatch.put(key, value)` +#### `chainedBatch.put(key, value[, options])` -Queue a `put` operation on this batch. This may throw if `key` or `value` is invalid. +Queue a `put` operation on this batch. This may throw if `key` or `value` is invalid. There are no `options` by default but implementations may add theirs. -#### `chainedBatch.del(key)` +#### `chainedBatch.del(key[, options])` -Queue a `del` operation on this batch. This may throw if `key` is invalid. +Queue a `del` operation on this batch. This may throw if `key` is invalid. There are no `options` by default but implementations may add theirs. #### `chainedBatch.clear()` @@ -358,7 +353,7 @@ Support of other key and value types depends on the implementation as well as it Each of these methods will receive exactly the number and order of arguments described. Optional arguments will receive sensible defaults. All callbacks are error-first and must be asynchronous. -If an operation within your implementation is synchronous, be sure to invoke the callback on a next tick using `process.nextTick` or some other means of microtask scheduling. For convenience, the prototypes of `AbstractLevelDOWN`, `AbstractIterator` and `AbstractChainedBatch` include a `_nextTick` method that is compatible with node and browsers. +If an operation within your implementation is synchronous, be sure to invoke the callback on a next tick using `queueMicrotask`, `process.nextTick` or some other means of microtask scheduling. For convenience, the prototypes of `AbstractLevelDOWN`, `AbstractIterator` and `AbstractChainedBatch` include a `_nextTick` method that is compatible with node and browsers. ### `db = AbstractLevelDOWN([manifest])` @@ -499,13 +494,13 @@ The default `_end()` invokes `callback` on a next tick. Overriding is optional. The first argument to this constructor must be an instance of your `AbstractLevelDOWN` implementation. The constructor will set `chainedBatch.db` which is used to access `db._serialize*` and ensures that `db` will not be garbage collected in case there are no other references to it. -#### `chainedBatch._put(key, value)` +#### `chainedBatch._put(key, value, options)` -Queue a `put` operation on this batch. +Queue a `put` operation on this batch. There are no default options but `options` will always be an object. -#### `chainedBatch._del(key)` +#### `chainedBatch._del(key, options)` -Queue a `del` operation on this batch. +Queue a `del` operation on this batch. There are no default options but `options` will always be an object. #### `chainedBatch._clear()` @@ -570,7 +565,6 @@ This also serves as a signal to users of your implementation. The following opti - Reads don't operate on a [snapshot](#iterator) - Snapshots are created asynchronously - `createIfMissing` and `errorIfExists`: set to `false` if `db._open()` does not support these options. -- `legacyRange`: set to `false` if your iterator does not support the legacy `start` and `end` range options. This metadata will be moved to manifests (`db.supports`) in the future. diff --git a/abstract-chained-batch.js b/abstract-chained-batch.js index bcdb9fa9..b167c0e1 100644 --- a/abstract-chained-batch.js +++ b/abstract-chained-batch.js @@ -1,4 +1,6 @@ -var nextTick = require('./next-tick') +'use strict' + +const emptyOptions = Object.freeze({}) function AbstractChainedBatch (db) { if (typeof db !== 'object' || db === null) { @@ -16,38 +18,38 @@ AbstractChainedBatch.prototype._checkWritten = function () { } } -AbstractChainedBatch.prototype.put = function (key, value) { +AbstractChainedBatch.prototype.put = function (key, value, options) { this._checkWritten() - var err = this.db._checkKey(key) || this.db._checkValue(value) + const err = this.db._checkKey(key) || this.db._checkValue(value) if (err) throw err key = this.db._serializeKey(key) value = this.db._serializeValue(value) - this._put(key, value) + this._put(key, value, options != null ? options : emptyOptions) return this } -AbstractChainedBatch.prototype._put = function (key, value) { - this._operations.push({ type: 'put', key: key, value: value }) +AbstractChainedBatch.prototype._put = function (key, value, options) { + this._operations.push({ ...options, type: 'put', key, value }) } -AbstractChainedBatch.prototype.del = function (key) { +AbstractChainedBatch.prototype.del = function (key, options) { this._checkWritten() - var err = this.db._checkKey(key) + const err = this.db._checkKey(key) if (err) throw err key = this.db._serializeKey(key) - this._del(key) + this._del(key, options != null ? options : emptyOptions) return this } -AbstractChainedBatch.prototype._del = function (key) { - this._operations.push({ type: 'del', key: key }) +AbstractChainedBatch.prototype._del = function (key, options) { + this._operations.push({ ...options, type: 'del', key }) } AbstractChainedBatch.prototype.clear = function () { @@ -64,7 +66,9 @@ AbstractChainedBatch.prototype._clear = function () { AbstractChainedBatch.prototype.write = function (options, callback) { this._checkWritten() - if (typeof options === 'function') { callback = options } + if (typeof options === 'function') { + callback = options + } if (typeof callback !== 'function') { throw new Error('write() requires a callback argument') } @@ -81,6 +85,6 @@ AbstractChainedBatch.prototype._write = function (options, callback) { } // Expose browser-compatible nextTick for dependents -AbstractChainedBatch.prototype._nextTick = nextTick +AbstractChainedBatch.prototype._nextTick = require('./next-tick') module.exports = AbstractChainedBatch diff --git a/abstract-iterator.js b/abstract-iterator.js index 8fb0f9cb..91fb536d 100644 --- a/abstract-iterator.js +++ b/abstract-iterator.js @@ -1,4 +1,4 @@ -var nextTick = require('./next-tick') +'use strict' function AbstractIterator (db) { if (typeof db !== 'object' || db === null) { @@ -11,33 +11,31 @@ function AbstractIterator (db) { } AbstractIterator.prototype.next = function (callback) { - var self = this - if (typeof callback !== 'function') { throw new Error('next() requires a callback argument') } - if (self._ended) { - nextTick(callback, new Error('cannot call next() after end()')) - return self + if (this._ended) { + this._nextTick(callback, new Error('cannot call next() after end()')) + return this } - if (self._nexting) { - nextTick(callback, new Error('cannot call next() before previous next() has completed')) - return self + if (this._nexting) { + this._nextTick(callback, new Error('cannot call next() before previous next() has completed')) + return this } - self._nexting = true - self._next(function () { - self._nexting = false - callback.apply(null, arguments) + this._nexting = true + this._next((err, ...rest) => { + this._nexting = false + callback(err, ...rest) }) - return self + return this } AbstractIterator.prototype._next = function (callback) { - nextTick(callback) + this._nextTick(callback) } AbstractIterator.prototype.seek = function (target) { @@ -60,7 +58,7 @@ AbstractIterator.prototype.end = function (callback) { } if (this._ended) { - return nextTick(callback, new Error('end() already called on iterator')) + return this._nextTick(callback, new Error('end() already called on iterator')) } this._ended = true @@ -68,10 +66,10 @@ AbstractIterator.prototype.end = function (callback) { } AbstractIterator.prototype._end = function (callback) { - nextTick(callback) + this._nextTick(callback) } // Expose browser-compatible nextTick for dependents -AbstractIterator.prototype._nextTick = nextTick +AbstractIterator.prototype._nextTick = require('./next-tick') module.exports = AbstractIterator diff --git a/abstract-leveldown.js b/abstract-leveldown.js index 5039cf32..eaa51297 100644 --- a/abstract-leveldown.js +++ b/abstract-leveldown.js @@ -1,11 +1,11 @@ -var xtend = require('xtend') -var supports = require('level-supports') -var Buffer = require('buffer').Buffer -var AbstractIterator = require('./abstract-iterator') -var AbstractChainedBatch = require('./abstract-chained-batch') -var nextTick = require('./next-tick') -var hasOwnProperty = Object.prototype.hasOwnProperty -var rangeOptions = 'start end gt gte lt lte'.split(' ') +'use strict' + +const supports = require('level-supports') +const isBuffer = require('is-buffer') +const AbstractIterator = require('./abstract-iterator') +const AbstractChainedBatch = require('./abstract-chained-batch') +const hasOwnProperty = Object.prototype.hasOwnProperty +const rangeOptions = ['lt', 'lte', 'gt', 'gte'] function AbstractLevelDOWN (manifest) { this.status = 'new' @@ -17,8 +17,7 @@ function AbstractLevelDOWN (manifest) { } AbstractLevelDOWN.prototype.open = function (options, callback) { - var self = this - var oldStatus = this.status + const oldStatus = this.status if (typeof options === 'function') callback = options @@ -32,41 +31,40 @@ AbstractLevelDOWN.prototype.open = function (options, callback) { options.errorIfExists = !!options.errorIfExists this.status = 'opening' - this._open(options, function (err) { + this._open(options, (err) => { if (err) { - self.status = oldStatus + this.status = oldStatus return callback(err) } - self.status = 'open' + this.status = 'open' callback() }) } AbstractLevelDOWN.prototype._open = function (options, callback) { - nextTick(callback) + this._nextTick(callback) } AbstractLevelDOWN.prototype.close = function (callback) { - var self = this - var oldStatus = this.status + const oldStatus = this.status if (typeof callback !== 'function') { throw new Error('close() requires a callback argument') } this.status = 'closing' - this._close(function (err) { + this._close((err) => { if (err) { - self.status = oldStatus + this.status = oldStatus return callback(err) } - self.status = 'closed' + this.status = 'closed' callback() }) } AbstractLevelDOWN.prototype._close = function (callback) { - nextTick(callback) + this._nextTick(callback) } AbstractLevelDOWN.prototype.get = function (key, options, callback) { @@ -76,8 +74,8 @@ AbstractLevelDOWN.prototype.get = function (key, options, callback) { throw new Error('get() requires a callback argument') } - var err = this._checkKey(key) - if (err) return nextTick(callback, err) + const err = this._checkKey(key) + if (err) return this._nextTick(callback, err) key = this._serializeKey(key) @@ -89,7 +87,7 @@ AbstractLevelDOWN.prototype.get = function (key, options, callback) { } AbstractLevelDOWN.prototype._get = function (key, options, callback) { - nextTick(function () { callback(new Error('NotFound')) }) + this._nextTick(function () { callback(new Error('NotFound')) }) } AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { @@ -99,8 +97,8 @@ AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { throw new Error('put() requires a callback argument') } - var err = this._checkKey(key) || this._checkValue(value) - if (err) return nextTick(callback, err) + const err = this._checkKey(key) || this._checkValue(value) + if (err) return this._nextTick(callback, err) key = this._serializeKey(key) value = this._serializeValue(value) @@ -111,7 +109,7 @@ AbstractLevelDOWN.prototype.put = function (key, value, options, callback) { } AbstractLevelDOWN.prototype._put = function (key, value, options, callback) { - nextTick(callback) + this._nextTick(callback) } AbstractLevelDOWN.prototype.del = function (key, options, callback) { @@ -121,8 +119,8 @@ AbstractLevelDOWN.prototype.del = function (key, options, callback) { throw new Error('del() requires a callback argument') } - var err = this._checkKey(key) - if (err) return nextTick(callback, err) + const err = this._checkKey(key) + if (err) return this._nextTick(callback, err) key = this._serializeKey(key) @@ -132,7 +130,7 @@ AbstractLevelDOWN.prototype.del = function (key, options, callback) { } AbstractLevelDOWN.prototype._del = function (key, options, callback) { - nextTick(callback) + this._nextTick(callback) } AbstractLevelDOWN.prototype.batch = function (array, options, callback) { @@ -147,36 +145,36 @@ AbstractLevelDOWN.prototype.batch = function (array, options, callback) { } if (!Array.isArray(array)) { - return nextTick(callback, new Error('batch(array) requires an array argument')) + return this._nextTick(callback, new Error('batch(array) requires an array argument')) } if (array.length === 0) { - return nextTick(callback) + return this._nextTick(callback) } if (typeof options !== 'object' || options === null) options = {} - var serialized = new Array(array.length) + const serialized = new Array(array.length) - for (var i = 0; i < array.length; i++) { + for (let i = 0; i < array.length; i++) { if (typeof array[i] !== 'object' || array[i] === null) { - return nextTick(callback, new Error('batch(array) element must be an object and not `null`')) + return this._nextTick(callback, new Error('batch(array) element must be an object and not `null`')) } - var e = xtend(array[i]) + const e = Object.assign({}, array[i]) if (e.type !== 'put' && e.type !== 'del') { - return nextTick(callback, new Error("`type` must be 'put' or 'del'")) + return this._nextTick(callback, new Error("`type` must be 'put' or 'del'")) } - var err = this._checkKey(e.key) - if (err) return nextTick(callback, err) + const err = this._checkKey(e.key) + if (err) return this._nextTick(callback, err) e.key = this._serializeKey(e.key) if (e.type === 'put') { - var valueErr = this._checkValue(e.value) - if (valueErr) return nextTick(callback, valueErr) + const valueErr = this._checkValue(e.value) + if (valueErr) return this._nextTick(callback, valueErr) e.value = this._serializeValue(e.value) } @@ -188,7 +186,7 @@ AbstractLevelDOWN.prototype.batch = function (array, options, callback) { } AbstractLevelDOWN.prototype._batch = function (array, options, callback) { - nextTick(callback) + this._nextTick(callback) } AbstractLevelDOWN.prototype.clear = function (options, callback) { @@ -212,25 +210,24 @@ AbstractLevelDOWN.prototype._clear = function (options, callback) { options.keyAsBuffer = true options.valueAsBuffer = true - var iterator = this._iterator(options) - var emptyOptions = {} - var self = this + const iterator = this._iterator(options) + const emptyOptions = {} - var next = function (err) { + const next = (err) => { if (err) { return iterator.end(function () { callback(err) }) } - iterator.next(function (err, key) { + iterator.next((err, key) => { if (err) return next(err) if (key === undefined) return iterator.end(callback) // This could be optimized by using a batch, but the default _clear // is not meant to be fast. Implementations have more room to optimize // if they override _clear. Note: using _del bypasses key serialization. - self._del(key, emptyOptions, next) + this._del(key, emptyOptions, next) }) } @@ -251,12 +248,16 @@ AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) { } function cleanRangeOptions (db, options) { - var result = {} + const result = {} - for (var k in options) { + for (const k in options) { if (!hasOwnProperty.call(options, k)) continue - var opt = options[k] + if (k === 'start' || k === 'end') { + throw new Error('Legacy range options ("start" and "end") have been removed') + } + + let opt = options[k] if (isRangeOption(k)) { // Note that we don't reject nullish and empty options here. While @@ -299,7 +300,7 @@ AbstractLevelDOWN.prototype._serializeValue = function (value) { AbstractLevelDOWN.prototype._checkKey = function (key) { if (key === null || key === undefined) { return new Error('key cannot be `null` or `undefined`') - } else if (Buffer.isBuffer(key) && key.length === 0) { + } else if (isBuffer(key) && key.length === 0) { // TODO: replace with typed array check return new Error('key cannot be an empty Buffer') } else if (key === '') { return new Error('key cannot be an empty String') @@ -315,6 +316,8 @@ AbstractLevelDOWN.prototype._checkValue = function (value) { } // Expose browser-compatible nextTick for dependents -AbstractLevelDOWN.prototype._nextTick = nextTick +// TODO: rename _nextTick to _queueMicrotask +// TODO: after we drop node 10, also use queueMicrotask in node +AbstractLevelDOWN.prototype._nextTick = require('./next-tick') module.exports = AbstractLevelDOWN diff --git a/index.js b/index.js index 682a79ab..f760becf 100644 --- a/index.js +++ b/index.js @@ -1,3 +1,5 @@ +'use strict' + exports.AbstractLevelDOWN = require('./abstract-leveldown') exports.AbstractIterator = require('./abstract-iterator') exports.AbstractChainedBatch = require('./abstract-chained-batch') diff --git a/next-tick-browser.js b/next-tick-browser.js index 3e424be5..d924b409 100644 --- a/next-tick-browser.js +++ b/next-tick-browser.js @@ -1 +1,11 @@ -module.exports = require('immediate') +'use strict' + +const queueMicrotask = require('queue-microtask') + +module.exports = function (fn, ...args) { + if (args.length === 0) { + queueMicrotask(fn) + } else { + queueMicrotask(() => fn(...args)) + } +} diff --git a/next-tick.js b/next-tick.js index 32b40935..cebc1fd8 100644 --- a/next-tick.js +++ b/next-tick.js @@ -1 +1,3 @@ +'use strict' + module.exports = process.nextTick diff --git a/package.json b/package.json index 56e2e2f8..75b55f76 100644 --- a/package.json +++ b/package.json @@ -9,29 +9,30 @@ }, "scripts": { "test": "standard && hallmark && nyc node test/self.js", - "test-browsers": "airtap --coverage --loopback airtap.local test/self.js", - "test-browser-local": "airtap --coverage --local test/self.js", + "test-browsers": "airtap --coverage test/self.js", + "test-browser-local": "airtap --coverage -p local --live test/self.js", "coverage": "nyc report --reporter=text-lcov | coveralls", "hallmark": "hallmark --fix", - "dependency-check": "dependency-check --no-dev -i buffer -i immediate . test/*.js", + "dependency-check": "dependency-check --no-dev -i buffer -i queue-microtask . test/*.js", "prepublishOnly": "npm run dependency-check" }, "dependencies": { "buffer": "^6.0.3", - "immediate": "^3.2.3", - "level-concat-iterator": "~2.0.0", - "level-supports": "~1.0.0", - "xtend": "~4.0.0" + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.0", + "queue-microtask": "^1.2.3" }, "devDependencies": { - "airtap": "^3.0.0", + "airtap": "^4.0.3", + "airtap-sauce": "^1.1.0", "coveralls": "^3.0.2", "dependency-check": "^4.1.0", "hallmark": "^3.1.0", "level-community": "^3.0.0", - "nyc": "^14.0.0", - "sinon": "^7.2.4", - "standard": "^14.0.0", + "nyc": "^15.1.0", + "sinon": "^10.0.0", + "standard": "^16.0.3", "tape": "^5.0.1" }, "hallmark": { @@ -49,6 +50,6 @@ "levelup" ], "engines": { - "node": ">=6" + "node": ">=10" } } diff --git a/test/batch-test.js b/test/batch-test.js index 39068831..9d36d5d3 100644 --- a/test/batch-test.js +++ b/test/batch-test.js @@ -1,6 +1,9 @@ -var db -var verifyNotFoundError = require('./util').verifyNotFoundError -var isTypedArray = require('./util').isTypedArray +'use strict' + +const verifyNotFoundError = require('./util').verifyNotFoundError +const isTypedArray = require('./util').isTypedArray + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -28,7 +31,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with null or undefined `value`', function (t) { - var illegalValues = [null, undefined] + const illegalValues = [null, undefined] t.plan(illegalValues.length) @@ -40,7 +43,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with missing `key`', function (t) { - var async = false + let async = false db.batch([{ type: 'put', value: 'foo1' }], function (err) { t.ok(err, 'got error') @@ -53,12 +56,12 @@ exports.args = function (test, testCommon) { }) test('test batch() with null or undefined `key`', function (t) { - var illegalKeys = [null, undefined] + const illegalKeys = [null, undefined] t.plan(illegalKeys.length * 3) illegalKeys.forEach(function (key) { - var async = false + let async = false db.batch([{ type: 'put', key: key, value: 'foo1' }], function (err) { t.ok(err, 'got error') @@ -71,7 +74,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with empty `key`', function (t) { - var illegalKeys = [ + const illegalKeys = [ { type: 'String', key: '' }, { type: 'Buffer', key: Buffer.alloc(0) }, { type: 'Array', key: [] } @@ -80,7 +83,7 @@ exports.args = function (test, testCommon) { t.plan(illegalKeys.length * 3) illegalKeys.forEach(function (item) { - var async = false + let async = false db.batch([{ type: 'put', key: item.key, value: 'foo1' }], function (err) { t.ok(err, 'got error') @@ -93,7 +96,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with missing `key` and `value`', function (t) { - var async = false + let async = false db.batch([{ type: 'put' }], function (err) { t.ok(err, 'got error') @@ -106,7 +109,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with missing `type`', function (t) { - var async = false + let async = false db.batch([{ key: 'key', value: 'value' }], function (err) { t.ok(err, 'got error') @@ -119,7 +122,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with wrong `type`', function (t) { - var async = false + let async = false db.batch([{ key: 'key', value: 'value', type: 'foo' }], function (err) { t.ok(err, 'got error') @@ -132,7 +135,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with missing array', function (t) { - var async = false + let async = false db.batch(function (err) { t.ok(err, 'got error') @@ -145,7 +148,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with undefined array', function (t) { - var async = false + let async = false db.batch(undefined, function (err) { t.ok(err, 'got error') @@ -158,7 +161,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with null array', function (t) { - var async = false + let async = false db.batch(null, function (err) { t.ok(err, 'got error') @@ -178,10 +181,10 @@ exports.args = function (test, testCommon) { }) ;[null, undefined, 1, true].forEach(function (element) { - var type = element === null ? 'null' : typeof element + const type = element === null ? 'null' : typeof element test('test batch() with ' + type + ' element', function (t) { - var async = false + let async = false db.batch([element], function (err) { t.ok(err, 'got error') @@ -195,7 +198,7 @@ exports.args = function (test, testCommon) { }) test('test batch() with empty array', function (t) { - var async = false + let async = false db.batch([], function (err) { t.error(err, 'no error from batch()') @@ -214,7 +217,7 @@ exports.batch = function (test, testCommon) { db.get('foo', function (err, value) { t.error(err) - var result + let result if (testCommon.encodings) { t.is(typeof value, 'string') @@ -240,14 +243,14 @@ exports.batch = function (test, testCommon) { ], function (err) { t.error(err) - var r = 0 - var done = function () { + let r = 0 + const done = function () { if (++r === 3) { t.end() } } db.get('foobatch1', function (err, value) { t.error(err) - var result + let result if (testCommon.encodings) { t.is(typeof value, 'string') result = value @@ -270,7 +273,7 @@ exports.batch = function (test, testCommon) { db.get('foobatch3', function (err, value) { t.error(err) - var result + let result if (testCommon.encodings) { t.is(typeof value, 'string') result = value @@ -291,7 +294,7 @@ exports.atomic = function (test, testCommon) { test('test multiple batch()', function (t) { t.plan(4) - var async = false + let async = false db.batch([ { type: 'put', key: 'foobah1', value: 'bar1' }, diff --git a/test/chained-batch-test.js b/test/chained-batch-test.js index 626b0b91..b8a8628d 100644 --- a/test/chained-batch-test.js +++ b/test/chained-batch-test.js @@ -1,23 +1,25 @@ -var collectEntries = require('level-concat-iterator') +'use strict' -var db +const collectEntries = require('level-concat-iterator') + +let db function collectBatchOps (batch) { - var _put = batch._put - var _del = batch._del - var _operations = [] + const _put = batch._put + const _del = batch._del + const _operations = [] if (typeof _put !== 'function' || typeof _del !== 'function') { return batch._operations } batch._put = function (key, value) { - _operations.push({ type: 'put', key: key, value: value }) + _operations.push({ type: 'put', key, value }) return _put.apply(this, arguments) } batch._del = function (key) { - _operations.push({ type: 'del', key: key }) + _operations.push({ type: 'del', key }) return _del.apply(this, arguments) } @@ -82,7 +84,7 @@ exports.args = function (test, testCommon) { }) test('test batch#put() with null or undefined `value`', function (t) { - var illegalValues = [null, undefined] + const illegalValues = [null, undefined] t.plan(illegalValues.length) illegalValues.forEach(function (value) { @@ -106,7 +108,7 @@ exports.args = function (test, testCommon) { }) test('test batch#del() with null or undefined `key`', function (t) { - var illegalKeys = [null, undefined] + const illegalKeys = [null, undefined] t.plan(illegalKeys.length) illegalKeys.forEach(function (key) { @@ -135,7 +137,7 @@ exports.args = function (test, testCommon) { }) test('test batch#put() after write()', function (t) { - var batch = db.batch().put('foo', 'bar') + const batch = db.batch().put('foo', 'bar') batch.write(function () {}) try { batch.put('boom', 'bang') @@ -148,7 +150,7 @@ exports.args = function (test, testCommon) { }) test('test batch#del() after write()', function (t) { - var batch = db.batch().put('foo', 'bar') + const batch = db.batch().put('foo', 'bar') batch.write(function () {}) try { batch.del('foo') @@ -161,7 +163,7 @@ exports.args = function (test, testCommon) { }) test('test batch#clear() after write()', function (t) { - var batch = db.batch().put('foo', 'bar') + const batch = db.batch().put('foo', 'bar') batch.write(function () {}) try { batch.clear() @@ -174,7 +176,7 @@ exports.args = function (test, testCommon) { }) test('test batch#write() after write()', function (t) { - var batch = db.batch().put('foo', 'bar') + const batch = db.batch().put('foo', 'bar') batch.write(function () {}) try { batch.write(function () {}) @@ -187,8 +189,8 @@ exports.args = function (test, testCommon) { }) testCommon.serialize && test('test serialize object', function (t) { - var batch = db.batch() - var ops = collectBatchOps(batch) + const batch = db.batch() + const ops = collectBatchOps(batch) batch .put({ foo: 'bar' }, { beep: 'boop' }) @@ -205,9 +207,9 @@ exports.args = function (test, testCommon) { testCommon.serialize && test('test custom _serialize*', function (t) { t.plan(4) - var _db = Object.create(db) - var batch = _db.batch() - var ops = collectBatchOps(batch) + const _db = Object.create(db) + const batch = _db.batch() + const ops = collectBatchOps(batch) _db._serializeKey = function (key) { t.same(key, { foo: 'bar' }) @@ -235,7 +237,7 @@ exports.args = function (test, testCommon) { }) test('test batch#write() with no operations', function (t) { - var async = false + let async = false db.batch().write(function (err) { t.ifError(err, 'no error from write()') @@ -270,7 +272,7 @@ exports.batch = function (test, testCommon) { db.iterator({ keyAsBuffer: false, valueAsBuffer: false }), function (err, data) { t.error(err) t.equal(data.length, 3, 'correct number of entries') - var expected = [ + const expected = [ { key: 'foo', value: 'bar' }, { key: 'one', value: 'I' }, { key: 'two', value: 'II' } diff --git a/test/clear-range-test.js b/test/clear-range-test.js index 21586318..7df21849 100644 --- a/test/clear-range-test.js +++ b/test/clear-range-test.js @@ -1,9 +1,11 @@ -var concat = require('level-concat-iterator') +'use strict' -var data = (function () { - var d = [] - var i = 0 - var k +const concat = require('level-concat-iterator') + +const data = (function () { + const d = [] + let i = 0 + let k for (; i < 100; i++) { k = (i < 10 ? '0' : '') + i d.push({ @@ -31,7 +33,7 @@ exports.range = function (test, testCommon) { } function prepare (t, callback) { - var db = testCommon.factory() + const db = testCommon.factory() db.open(function (err) { t.ifError(err, 'no open error') @@ -50,7 +52,7 @@ exports.range = function (test, testCommon) { } function verify (t, db, expected) { - var it = db.iterator({ keyAsBuffer: false, valueAsBuffer: false }) + const it = db.iterator({ keyAsBuffer: false, valueAsBuffer: false }) concat(it, function (err, result) { t.ifError(err, 'no concat error') @@ -63,7 +65,7 @@ exports.range = function (test, testCommon) { function exclude (data, start, end, expectedLength) { data = data.slice() - var removed = data.splice(start, end - start + 1) // Inclusive + const removed = data.splice(start, end - start + 1) // Inclusive if (expectedLength != null) checkLength(removed, expectedLength) return data } @@ -151,12 +153,12 @@ exports.range = function (test, testCommon) { reverse: true }, data.slice(0, 51)) - // Starting key is actually '00' so it should avoid it + // First key is actually '00' so it should avoid it rangeTest('lte=0', { lte: '0' }, data) - // Starting key is actually '00' so it should avoid it + // First key is actually '00' so it should avoid it rangeTest('lt=0', { lt: '0' }, data) diff --git a/test/clear-test.js b/test/clear-test.js index e14a9799..9237affc 100644 --- a/test/clear-test.js +++ b/test/clear-test.js @@ -1,5 +1,7 @@ -var concat = require('level-concat-iterator') -var db +'use strict' + +const concat = require('level-concat-iterator') +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -35,8 +37,8 @@ exports.clear = function (test, testCommon) { test('test simple clear() on ' + type + ' keys', function (t) { t.plan(8) - var db = testCommon.factory() - var ops = keys.map(function (key) { + const db = testCommon.factory() + const ops = keys.map(function (key) { return { type: 'put', key: key, value: 'foo' } }) diff --git a/test/close-test.js b/test/close-test.js index f0a72cb1..76a13f5c 100644 --- a/test/close-test.js +++ b/test/close-test.js @@ -1,4 +1,6 @@ -var db +'use strict' + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) diff --git a/test/common.js b/test/common.js index de402e65..dfb3a6ee 100644 --- a/test/common.js +++ b/test/common.js @@ -1,6 +1,8 @@ +'use strict' + function testCommon (options) { - var factory = options.factory - var test = options.test + const factory = options.factory + const test = options.test if (typeof factory !== 'function') { throw new TypeError('factory must be a function') @@ -10,6 +12,10 @@ function testCommon (options) { throw new TypeError('test must be a function') } + if (options.legacyRange != null) { + throw new Error('The legacyRange option has been removed') + } + return { test: test, factory: factory, @@ -26,10 +32,6 @@ function testCommon (options) { seek: options.seek !== false, clear: !!options.clear, - // Allow skipping 'start' and 'end' tests - // TODO (next major): drop legacy range options - legacyRange: options.legacyRange !== false, - // Support running test suite on a levelup db. All options below this line // are undocumented and should not be used by abstract-leveldown db's (yet). promises: !!options.promises, diff --git a/test/del-test.js b/test/del-test.js index 87aedeac..a2fffca4 100644 --- a/test/del-test.js +++ b/test/del-test.js @@ -1,5 +1,8 @@ -var db -var verifyNotFoundError = require('./util').verifyNotFoundError +'use strict' + +const verifyNotFoundError = require('./util').verifyNotFoundError + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -39,11 +42,11 @@ exports.args = function (test, testCommon) { testCommon.serialize && test('test custom _serialize*', function (t) { t.plan(3) - var db = testCommon.factory() + const db = testCommon.factory() db._serializeKey = function (data) { return data } db._del = function (key, options, callback) { t.deepEqual(key, { foo: 'bar' }) - process.nextTick(callback) + this._nextTick(callback) } db.open(function () { db.del({ foo: 'bar' }, function (err) { diff --git a/test/factory-test.js b/test/factory-test.js index 4e1413ff..dec77a04 100644 --- a/test/factory-test.js +++ b/test/factory-test.js @@ -1,11 +1,13 @@ -var concat = require('level-concat-iterator') +'use strict' + +const concat = require('level-concat-iterator') module.exports = function (test, testCommon) { test('setUp common', testCommon.setUp) test('testCommon.factory() returns a unique database', function (t) { - var db1 = testCommon.factory() - var db2 = testCommon.factory() + const db1 = testCommon.factory() + const db2 = testCommon.factory() function close () { db1.close(function (err) { diff --git a/test/get-test.js b/test/get-test.js index 4a5c8644..ac24aea8 100644 --- a/test/get-test.js +++ b/test/get-test.js @@ -1,6 +1,9 @@ -var db -var verifyNotFoundError = require('./util').verifyNotFoundError -var isTypedArray = require('./util').isTypedArray +'use strict' + +const verifyNotFoundError = require('./util').verifyNotFoundError +const isTypedArray = require('./util').isTypedArray + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -40,11 +43,11 @@ exports.args = function (test, testCommon) { testCommon.serialize && test('test custom _serialize*', function (t) { t.plan(3) - var db = testCommon.factory() + const db = testCommon.factory() db._serializeKey = function (data) { return data } db._get = function (key, options, callback) { t.deepEqual(key, { foo: 'bar' }) - process.nextTick(callback) + this._nextTick(callback) } db.open(function () { db.get({ foo: 'bar' }, function (err) { @@ -62,11 +65,13 @@ exports.get = function (test, testCommon) { db.get('foo', function (err, value) { t.error(err) + let result + if (!testCommon.encodings) { t.ok(typeof value !== 'string', 'should not be string by default') if (isTypedArray(value)) { - var result = String.fromCharCode.apply(null, new Uint16Array(value)) + result = String.fromCharCode.apply(null, new Uint16Array(value)) } else { t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer) try { @@ -84,11 +89,13 @@ exports.get = function (test, testCommon) { db.get('foo', {}, function (err, value) { // same but with {} t.error(err) + let result + if (!testCommon.encodings) { t.ok(typeof value !== 'string', 'should not be string by default') if (isTypedArray(value)) { - var result = String.fromCharCode.apply(null, new Uint16Array(value)) + result = String.fromCharCode.apply(null, new Uint16Array(value)) } else { t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer) try { @@ -117,12 +124,12 @@ exports.get = function (test, testCommon) { test('test simultaniously get()', function (t) { db.put('hello', 'world', function (err) { t.error(err) - var r = 0 - var done = function () { + let r = 0 + const done = function () { if (++r === 20) { t.end() } } - var i = 0 - var j = 0 + let i = 0 + let j = 0 for (; i < 10; ++i) { db.get('hello', function (err, value) { @@ -149,7 +156,7 @@ exports.get = function (test, testCommon) { db.put('hello', 'world', function (err) { t.error(err) - var async = false + let async = false db.get('not found', function (err, value) { t.ok(err, 'should error') diff --git a/test/index.js b/test/index.js index 1ef97afc..b8705a62 100644 --- a/test/index.js +++ b/test/index.js @@ -1,8 +1,10 @@ -var common = require('./common') +'use strict' + +const common = require('./common') function suite (options) { - var testCommon = common(options) - var test = testCommon.test + const testCommon = common(options) + const test = testCommon.test require('./factory-test')(test, testCommon) require('./manifest-test')(test, testCommon) diff --git a/test/iterator-no-snapshot-test.js b/test/iterator-no-snapshot-test.js index c90df904..37510f97 100644 --- a/test/iterator-no-snapshot-test.js +++ b/test/iterator-no-snapshot-test.js @@ -1,4 +1,6 @@ -var collectEntries = require('level-concat-iterator') +'use strict' + +const collectEntries = require('level-concat-iterator') exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -7,8 +9,8 @@ exports.setUp = function (test, testCommon) { exports.noSnapshot = function (test, testCommon) { function make (run) { return function (t) { - var db = testCommon.factory() - var operations = [ + const db = testCommon.factory() + const operations = [ { type: 'put', key: 'a', value: 'a' }, { type: 'put', key: 'b', value: 'b' }, { type: 'put', key: 'c', value: 'c' } @@ -23,7 +25,7 @@ exports.noSnapshot = function (test, testCommon) { // For this test it is important that we don't read eagerly. // NOTE: highWaterMark is not an abstract option atm, but // it is supported by leveldown, rocksdb and others. - var it = db.iterator({ highWaterMark: 0 }) + const it = db.iterator({ highWaterMark: 0 }) run(db, function (err) { t.ifError(err, 'no run error') @@ -38,7 +40,7 @@ exports.noSnapshot = function (test, testCommon) { collectEntries(it, function (err, entries) { t.ifError(err, 'no iterator error') - var kv = entries.map(function (entry) { + const kv = entries.map(function (entry) { return entry.key.toString() + entry.value.toString() }) diff --git a/test/iterator-range-test.js b/test/iterator-range-test.js index a691503a..88a9b009 100644 --- a/test/iterator-range-test.js +++ b/test/iterator-range-test.js @@ -1,12 +1,13 @@ -var collectEntries = require('level-concat-iterator') -var xtend = require('xtend') +'use strict' -var db +const collectEntries = require('level-concat-iterator') -var data = (function () { - var d = [] - var i = 0 - var k +let db + +const data = (function () { + const d = [] + let i = 0 + let k for (; i < 100; i++) { k = (i < 10 ? '0' : '') + i d.push({ @@ -35,12 +36,9 @@ exports.setUp = function (test, testCommon) { exports.range = function (test, testCommon) { function rangeTest (name, opts, expected) { - if (!testCommon.legacyRange && ('start' in opts || 'end' in opts)) { - return - } - opts.keyAsBuffer = false opts.valueAsBuffer = false + test(name, function (t) { collectEntries(db.iterator(opts), function (err, result) { t.error(err) @@ -53,19 +51,7 @@ exports.range = function (test, testCommon) { // Test the documented promise that in reverse mode, // "the returned entries are the same, but in reverse". if (!opts.reverse && !('limit' in opts)) { - var reverseOpts = xtend(opts, { reverse: true }) - - // Swap start & end options - if (('start' in opts) && ('end' in opts)) { - reverseOpts.end = opts.start - reverseOpts.start = opts.end - } else if ('start' in opts) { - reverseOpts.end = opts.start - delete reverseOpts.start - } else if ('end' in opts) { - reverseOpts.start = opts.end - delete reverseOpts.end - } + const reverseOpts = Object.assign({}, opts, { reverse: true }) rangeTest( name + ' (flipped)', @@ -85,44 +71,23 @@ exports.range = function (test, testCommon) { gte: '00' }, data) - rangeTest('test iterator with start=00 - legacy', { - start: '00' - }, data) - rangeTest('test iterator with gte=50', { gte: '50' }, data.slice(50)) - rangeTest('test iterator with start=50 - legacy', { - start: '50' - }, data.slice(50)) - rangeTest('test iterator with lte=50 and reverse=true', { lte: '50', reverse: true }, data.slice().reverse().slice(49)) - rangeTest('test iterator with start=50 and reverse=true - legacy', { - start: '50', - reverse: true - }, data.slice().reverse().slice(49)) - rangeTest('test iterator with gte=49.5 (midway)', { gte: '49.5' }, data.slice(50)) - rangeTest('test iterator with start=49.5 (midway) - legacy', { - start: '49.5' - }, data.slice(50)) - rangeTest('test iterator with gte=49999 (midway)', { gte: '49999' }, data.slice(50)) - rangeTest('test iterator with start=49999 (midway) - legacy', { - start: '49999' - }, data.slice(50)) - rangeTest('test iterator with lte=49.5 (midway) and reverse=true', { lte: '49.5', reverse: true @@ -138,27 +103,14 @@ exports.range = function (test, testCommon) { reverse: true }, data.slice().reverse().slice(50)) - rangeTest('test iterator with start=49.5 (midway) and reverse=true - legacy', { - start: '49.5', - reverse: true - }, data.slice().reverse().slice(50)) - rangeTest('test iterator with lte=50', { lte: '50' }, data.slice(0, 51)) - rangeTest('test iterator with end=50 - legacy', { - end: '50' - }, data.slice(0, 51)) - rangeTest('test iterator with lte=50.5 (midway)', { lte: '50.5' }, data.slice(0, 51)) - rangeTest('test iterator with end=50.5 (midway) - legacy', { - end: '50.5' - }, data.slice(0, 51)) - rangeTest('test iterator with lte=50555 (midway)', { lte: '50555' }, data.slice(0, 51)) @@ -167,10 +119,6 @@ exports.range = function (test, testCommon) { lt: '50555' }, data.slice(0, 51)) - rangeTest('test iterator with end=50555 (midway) - legacy', { - end: '50555' - }, data.slice(0, 51)) - rangeTest('test iterator with gte=50.5 (midway) and reverse=true', { gte: '50.5', reverse: true @@ -181,31 +129,21 @@ exports.range = function (test, testCommon) { reverse: true }, data.slice().reverse().slice(0, 49)) - rangeTest('test iterator with end=50.5 (midway) and reverse=true - legacy', { - end: '50.5', - reverse: true - }, data.slice().reverse().slice(0, 49)) - rangeTest('test iterator with gt=50 and reverse=true', { gt: '50', reverse: true }, data.slice().reverse().slice(0, 49)) - // end='0', starting key is actually '00' so it should avoid it + // first key is actually '00' so it should avoid it rangeTest('test iterator with lte=0', { lte: '0' }, []) - // end='0', starting key is actually '00' so it should avoid it + // first key is actually '00' so it should avoid it rangeTest('test iterator with lt=0', { lt: '0' }, []) - // end='0', starting key is actually '00' so it should avoid it - rangeTest('test iterator with end=0 - legacy', { - end: '0' - }, []) - rangeTest('test iterator with gte=30 and lte=70', { gte: '30', lte: '70' @@ -216,11 +154,6 @@ exports.range = function (test, testCommon) { lt: '71' }, data.slice(30, 71)) - rangeTest('test iterator with start=30 and end=70 - legacy', { - start: '30', - end: '70' - }, data.slice(30, 71)) - rangeTest('test iterator with gte=30 and lte=70 and reverse=true', { lte: '70', gte: '30', @@ -233,12 +166,6 @@ exports.range = function (test, testCommon) { reverse: true }, data.slice().reverse().slice(29, 70)) - rangeTest('test iterator with start=70 and end=30 and reverse=true - legacy', { - start: '70', - end: '30', - reverse: true - }, data.slice().reverse().slice(29, 70)) - rangeTest('test iterator with limit=20', { limit: 20 }, data.slice(0, 20)) @@ -248,11 +175,6 @@ exports.range = function (test, testCommon) { gte: '20' }, data.slice(20, 40)) - rangeTest('test iterator with limit=20 and start=20 - legacy', { - limit: 20, - start: '20' - }, data.slice(20, 40)) - rangeTest('test iterator with limit=20 and reverse=true', { limit: 20, reverse: true @@ -264,12 +186,6 @@ exports.range = function (test, testCommon) { reverse: true }, data.slice().reverse().slice(20, 40)) - rangeTest('test iterator with limit=20 and start=79 and reverse=true - legacy', { - limit: 20, - start: '79', - reverse: true - }, data.slice().reverse().slice(20, 40)) - // the default limit value from levelup is -1 rangeTest('test iterator with limit=-1 should iterate over whole database', { limit: -1 @@ -284,21 +200,11 @@ exports.range = function (test, testCommon) { lte: '50' }, data.slice(0, 20)) - rangeTest('test iterator with end after limit - legacy', { - limit: 20, - end: '50' - }, data.slice(0, 20)) - rangeTest('test iterator with lte before limit', { limit: 50, lte: '19' }, data.slice(0, 20)) - rangeTest('test iterator with end before limit - legacy', { - limit: 50, - end: '19' - }, data.slice(0, 20)) - rangeTest('test iterator with gte after database end', { gte: '9a' }, []) @@ -307,28 +213,15 @@ exports.range = function (test, testCommon) { gt: '9a' }, []) - rangeTest('test iterator with start after database end - legacy', { - start: '9a' - }, []) - rangeTest('test iterator with lte after database end and reverse=true', { lte: '9a', reverse: true }, data.slice().reverse()) - rangeTest('test iterator with start after database end and reverse=true - legacy', { - start: '9a', - reverse: true - }, data.slice().reverse()) - rangeTest('test iterator with lt after database end', { lt: 'a' }, data.slice()) - rangeTest('test iterator with end after database end - legacy', { - end: 'a' - }, data.slice()) - rangeTest('test iterator with lt at database end', { lt: data[data.length - 1].key }, data.slice(0, -1)) @@ -337,10 +230,6 @@ exports.range = function (test, testCommon) { lte: data[data.length - 1].key }, data.slice()) - rangeTest('test iterator with end at database end - legacy', { - end: data[data.length - 1].key - }, data.slice()) - rangeTest('test iterator with lt before database end', { lt: data[data.length - 2].key }, data.slice(0, -2)) @@ -349,10 +238,6 @@ exports.range = function (test, testCommon) { lte: data[data.length - 2].key }, data.slice(0, -1)) - rangeTest('test iterator with end before database end - legacy', { - end: data[data.length - 2].key - }, data.slice(0, -1)) - rangeTest('test iterator with lte and gte after database and reverse=true', { lte: '9b', gte: '9a', @@ -364,12 +249,6 @@ exports.range = function (test, testCommon) { gt: '9a', reverse: true }, []) - - rangeTest('test iterator with start and end after database and reverse=true - legacy', { - start: '9b', - end: '9a', - reverse: true - }, []) } exports.tearDown = function (test, testCommon) { diff --git a/test/iterator-seek-test.js b/test/iterator-seek-test.js index d153c9a0..673001c5 100644 --- a/test/iterator-seek-test.js +++ b/test/iterator-seek-test.js @@ -1,3 +1,5 @@ +'use strict' + exports.all = function (test, testCommon) { exports.setUp(test, testCommon) exports.sequence(test, testCommon) @@ -12,8 +14,8 @@ exports.setUp = function (test, testCommon) { exports.sequence = function (test, testCommon) { function make (name, testFn) { test(name, function (t) { - var db = testCommon.factory() - var done = function (err) { + const db = testCommon.factory() + const done = function (err) { t.error(err, 'no error from done()') db.close(function (err) { @@ -30,9 +32,9 @@ exports.sequence = function (test, testCommon) { } make('iterator#seek() throws if next() has not completed', function (db, t, done) { - var ite = db.iterator() - var error - var async = false + const ite = db.iterator() + let error + let async = false ite.next(function (err, key, value) { t.error(err, 'no error from next()') @@ -52,7 +54,7 @@ exports.sequence = function (test, testCommon) { }) make('iterator#seek() throws after end()', function (db, t, done) { - var ite = db.iterator() + const ite = db.iterator() // TODO: why call next? Can't we end immediately? ite.next(function (err, key, value) { @@ -60,7 +62,7 @@ exports.sequence = function (test, testCommon) { ite.end(function (err) { t.error(err, 'no error from end()') - var error + let error try { ite.seek('two') @@ -78,8 +80,8 @@ exports.sequence = function (test, testCommon) { exports.seek = function (test, testCommon) { function make (name, testFn) { test(name, function (t) { - var db = testCommon.factory() - var done = function (err) { + const db = testCommon.factory() + const done = function (err) { t.error(err, 'no error from done()') db.close(function (err) { @@ -104,7 +106,7 @@ exports.seek = function (test, testCommon) { } make('iterator#seek() to string target', function (db, t, done) { - var ite = db.iterator() + const ite = db.iterator() ite.seek('two') ite.next(function (err, key, value) { t.error(err, 'no error') @@ -121,7 +123,7 @@ exports.seek = function (test, testCommon) { if (testCommon.bufferKeys) { make('iterator#seek() to buffer target', function (db, t, done) { - var ite = db.iterator() + const ite = db.iterator() ite.seek(Buffer.from('two')) ite.next(function (err, key, value) { t.error(err, 'no error from next()') @@ -138,7 +140,7 @@ exports.seek = function (test, testCommon) { } make('iterator#seek() on reverse iterator', function (db, t, done) { - var ite = db.iterator({ reverse: true, limit: 1 }) + const ite = db.iterator({ reverse: true, limit: 1 }) ite.seek('three!') ite.next(function (err, key, value) { t.error(err, 'no error') @@ -149,7 +151,7 @@ exports.seek = function (test, testCommon) { }) make('iterator#seek() to out of range target', function (db, t, done) { - var ite = db.iterator() + const ite = db.iterator() ite.seek('zzz') ite.next(function (err, key, value) { t.error(err, 'no error') @@ -160,7 +162,7 @@ exports.seek = function (test, testCommon) { }) make('iterator#seek() on reverse iterator to out of range target', function (db, t, done) { - var ite = db.iterator({ reverse: true }) + const ite = db.iterator({ reverse: true }) ite.seek('zzz') ite.next(function (err, key, value) { t.error(err, 'no error') @@ -171,22 +173,22 @@ exports.seek = function (test, testCommon) { }) test('iterator#seek() respects range', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() db.open(function (err) { t.error(err, 'no error from open()') // Can't use Array.fill() because IE - var ops = [] + const ops = [] - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { ops.push({ type: 'put', key: String(i), value: String(i) }) } db.batch(ops, function (err) { t.error(err, 'no error from batch()') - var pending = 0 + let pending = 0 expect({ gt: '5' }, '4', undefined) expect({ gt: '5' }, '5', undefined) @@ -196,10 +198,6 @@ exports.seek = function (test, testCommon) { expect({ gte: '5' }, '5', '5') expect({ gte: '5' }, '6', '6') - expect({ start: '5' }, '4', undefined) - expect({ start: '5' }, '5', '5') - expect({ start: '5' }, '6', '6') - expect({ lt: '5' }, '4', '4') expect({ lt: '5' }, '5', undefined) expect({ lt: '5' }, '6', undefined) @@ -208,10 +206,6 @@ exports.seek = function (test, testCommon) { expect({ lte: '5' }, '5', '5') expect({ lte: '5' }, '6', undefined) - expect({ end: '5' }, '4', '4') - expect({ end: '5' }, '5', '5') - expect({ end: '5' }, '6', undefined) - expect({ lt: '5', reverse: true }, '4', '4') expect({ lt: '5', reverse: true }, '5', undefined) expect({ lt: '5', reverse: true }, '6', undefined) @@ -220,10 +214,6 @@ exports.seek = function (test, testCommon) { expect({ lte: '5', reverse: true }, '5', '5') expect({ lte: '5', reverse: true }, '6', undefined) - expect({ start: '5', reverse: true }, '4', '4') - expect({ start: '5', reverse: true }, '5', '5') - expect({ start: '5', reverse: true }, '6', undefined) - expect({ gt: '5', reverse: true }, '4', undefined) expect({ gt: '5', reverse: true }, '5', undefined) expect({ gt: '5', reverse: true }, '6', '6') @@ -232,10 +222,6 @@ exports.seek = function (test, testCommon) { expect({ gte: '5', reverse: true }, '5', '5') expect({ gte: '5', reverse: true }, '6', '6') - expect({ end: '5', reverse: true }, '4', undefined) - expect({ end: '5', reverse: true }, '5', '5') - expect({ end: '5', reverse: true }, '6', '6') - expect({ gt: '7', lt: '8' }, '7', undefined) expect({ gte: '7', lt: '8' }, '7', '7') expect({ gte: '7', lt: '8' }, '8', undefined) @@ -243,14 +229,14 @@ exports.seek = function (test, testCommon) { function expect (range, target, expected) { pending++ - var ite = db.iterator(range) + const ite = db.iterator(range) ite.seek(target) ite.next(function (err, key, value) { t.error(err, 'no error from next()') - var json = JSON.stringify(range) - var msg = 'seek(' + target + ') on ' + json + ' yields ' + expected + const json = JSON.stringify(range) + const msg = 'seek(' + target + ') on ' + json + ' yields ' + expected if (expected === undefined) { t.equal(value, undefined, msg) diff --git a/test/iterator-snapshot-test.js b/test/iterator-snapshot-test.js index 7c022b02..ab526307 100644 --- a/test/iterator-snapshot-test.js +++ b/test/iterator-snapshot-test.js @@ -1,3 +1,5 @@ +'use strict' + exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) } @@ -5,7 +7,7 @@ exports.setUp = function (test, testCommon) { exports.snapshot = function (test, testCommon) { function make (run) { return function (t) { - var db = testCommon.factory() + const db = testCommon.factory() db.open(function (err) { t.ifError(err, 'no open error') @@ -16,7 +18,7 @@ exports.snapshot = function (test, testCommon) { // For this test it is important that we don't read eagerly. // NOTE: highWaterMark is not an abstract option atm, but // it is supported by leveldown, rocksdb and others. - var it = db.iterator({ highWaterMark: 0 }) + const it = db.iterator({ highWaterMark: 0 }) run(t, db, it, function end (err) { t.ifError(err, 'no run error') diff --git a/test/iterator-test.js b/test/iterator-test.js index 6ce85569..9925508b 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -1,4 +1,6 @@ -var db +'use strict' + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -10,14 +12,14 @@ exports.setUp = function (test, testCommon) { exports.args = function (test, testCommon) { test('test iterator has db reference', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() // For levelup compat: may return iterator of an underlying db, that's okay. t.ok(iterator.db === db || iterator.db) iterator.end(t.end.bind(t)) }) test('test argument-less iterator#next() throws', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() t.throws( iterator.next.bind(iterator), /Error: next\(\) requires a callback argument/, @@ -27,7 +29,7 @@ exports.args = function (test, testCommon) { }) test('test argument-less iterator#end() after next() throws', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() iterator.next(function () { t.throws( iterator.end.bind(iterator), @@ -39,7 +41,7 @@ exports.args = function (test, testCommon) { }) test('test argument-less iterator#end() throws', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() t.throws( iterator.end.bind(iterator), /Error: end\(\) requires a callback argument/, @@ -49,8 +51,8 @@ exports.args = function (test, testCommon) { }) test('test iterator#next returns this', function (t) { - var iterator = db.iterator() - var self = iterator.next(function () {}) + const iterator = db.iterator() + const self = iterator.next(function () {}) t.ok(iterator === self) iterator.end(t.end.bind(t)) }) @@ -58,11 +60,11 @@ exports.args = function (test, testCommon) { exports.sequence = function (test, testCommon) { test('test twice iterator#end() callback with error', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() iterator.end(function (err) { t.error(err) - var async = false + let async = false iterator.end(function (err2) { t.ok(err2, 'returned error') @@ -77,11 +79,11 @@ exports.sequence = function (test, testCommon) { }) test('test iterator#next after iterator#end() callback with error', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() iterator.end(function (err) { t.error(err) - var async = false + let async = false iterator.next(function (err2) { t.ok(err2, 'returned error') @@ -96,7 +98,7 @@ exports.sequence = function (test, testCommon) { }) test('test twice iterator#next() throws', function (t) { - var iterator = db.iterator() + const iterator = db.iterator() iterator.next(function (err) { t.error(err) iterator.end(function (err) { @@ -105,7 +107,7 @@ exports.sequence = function (test, testCommon) { }) }) - var async = false + let async = false iterator.next(function (err) { t.ok(err, 'returned error') @@ -120,17 +122,17 @@ exports.sequence = function (test, testCommon) { exports.iterator = function (test, testCommon) { test('test simple iterator()', function (t) { - var data = [ + const data = [ { type: 'put', key: 'foobatch1', value: 'bar1' }, { type: 'put', key: 'foobatch2', value: 'bar2' }, { type: 'put', key: 'foobatch3', value: 'bar3' } ] - var idx = 0 + let idx = 0 db.batch(data, function (err) { t.error(err) - var iterator = db.iterator() - var fn = function (err, key, value) { + const iterator = db.iterator() + const fn = function (err, key, value) { t.error(err) if (key && value) { if (testCommon.encodings) { @@ -142,7 +144,7 @@ exports.iterator = function (test, testCommon) { } t.is(key.toString(), data[idx].key, 'correct key') t.is(value.toString(), data[idx].value, 'correct value') - process.nextTick(next) + db._nextTick(next) idx++ } else { // end t.ok(err == null, 'err argument is nullish') @@ -154,7 +156,7 @@ exports.iterator = function (test, testCommon) { }) } } - var next = function () { + const next = function () { iterator.next(fn) } diff --git a/test/leveldown-test.js b/test/leveldown-test.js index a6407686..f8e21c7c 100644 --- a/test/leveldown-test.js +++ b/test/leveldown-test.js @@ -1,8 +1,10 @@ +'use strict' + module.exports = function (test, testCommon) { test('setUp common', testCommon.setUp) test('test database open method exists', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() t.ok(db, 'database object returned') t.ok(typeof db.open === 'function', 'open() function exists') t.end() diff --git a/test/manifest-test.js b/test/manifest-test.js index 080c0846..3c9bcc94 100644 --- a/test/manifest-test.js +++ b/test/manifest-test.js @@ -1,4 +1,6 @@ -var suite = require('level-supports/test') +'use strict' + +const suite = require('level-supports/test') module.exports = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -6,7 +8,7 @@ module.exports = function (test, testCommon) { suite(test, testCommon) testCommon.status && test('manifest has status', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() t.is(db.supports.status, true) // The semantics of not opening or closing a new db are unclear diff --git a/test/open-create-if-missing-test.js b/test/open-create-if-missing-test.js index 388281a3..30aa4a2c 100644 --- a/test/open-create-if-missing-test.js +++ b/test/open-create-if-missing-test.js @@ -1,11 +1,13 @@ +'use strict' + exports.setUp = function (test, testCommon) { test('setUp', testCommon.setUp) } exports.createIfMissing = function (test, testCommon) { test('test database open createIfMissing:false', function (t) { - var db = testCommon.factory() - var async = false + const db = testCommon.factory() + let async = false db.open({ createIfMissing: false }, function (err) { t.ok(err, 'error') diff --git a/test/open-error-if-exists-test.js b/test/open-error-if-exists-test.js index 96d3cd11..60781e64 100644 --- a/test/open-error-if-exists-test.js +++ b/test/open-error-if-exists-test.js @@ -1,17 +1,19 @@ +'use strict' + exports.setUp = function (test, testCommon) { test('setUp', testCommon.setUp) } exports.errorIfExists = function (test, testCommon) { test('test database open errorIfExists:true', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() db.open({}, function (err) { t.error(err) db.close(function (err) { t.error(err) - var async = false + let async = false db.open({ createIfMissing: false, errorIfExists: true }, function (err) { t.ok(err, 'error') diff --git a/test/open-test.js b/test/open-test.js index 8c5eea1a..c7068b0c 100644 --- a/test/open-test.js +++ b/test/open-test.js @@ -1,10 +1,12 @@ +'use strict' + exports.setUp = function (test, testCommon) { test('setUp', testCommon.setUp) } exports.args = function (test, testCommon) { testCommon.promises || test('test database open no-arg throws', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() t.throws( db.open.bind(db), /Error: open\(\) requires a callback argument/, @@ -14,7 +16,7 @@ exports.args = function (test, testCommon) { }) testCommon.promises || test('test callback-less, 1-arg, open() throws', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() t.throws( db.open.bind(db, {}), /Error: open\(\) requires a callback argument/, @@ -26,7 +28,7 @@ exports.args = function (test, testCommon) { exports.open = function (test, testCommon) { test('test database open, no options', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() // default createIfMissing=true, errorIfExists=false db.open(function (err) { @@ -38,7 +40,7 @@ exports.open = function (test, testCommon) { }) test('test database open, options and callback', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() // default createIfMissing=true, errorIfExists=false db.open({}, function (err) { @@ -50,7 +52,7 @@ exports.open = function (test, testCommon) { }) test('test database open, close and open', function (t) { - var db = testCommon.factory() + const db = testCommon.factory() db.open(function (err) { t.error(err) diff --git a/test/put-get-del-test.js b/test/put-get-del-test.js index 7d5aa384..cb7783f3 100644 --- a/test/put-get-del-test.js +++ b/test/put-get-del-test.js @@ -1,12 +1,13 @@ 'use strict' -var db -var verifyNotFoundError = require('./util').verifyNotFoundError -var testBuffer = Buffer.from('testbuffer') +const verifyNotFoundError = require('./util').verifyNotFoundError +const testBuffer = Buffer.from('testbuffer') + +let db function makeGetDelErrorTests (test, type, key, expectedError) { test('test get() with ' + type + ' causes error', function (t) { - var async = false + let async = false db.get(key, function (err) { t.ok(err, 'has error') @@ -20,7 +21,7 @@ function makeGetDelErrorTests (test, type, key, expectedError) { }) test('test del() with ' + type + ' causes error', function (t) { - var async = false + let async = false db.del(key, function (err) { t.ok(err, 'has error') @@ -36,7 +37,7 @@ function makeGetDelErrorTests (test, type, key, expectedError) { function makePutErrorTest (test, type, key, value, expectedError) { test('test put() with ' + type + ' causes error', function (t) { - var async = false + let async = false db.put(key, value, function (err) { t.ok(err, 'has error') @@ -51,16 +52,18 @@ function makePutErrorTest (test, type, key, value, expectedError) { } function makePutGetDelSuccessfulTest (test, testCommon, type, key, value, expectedResult) { - var hasExpectedResult = arguments.length === 6 + const hasExpectedResult = arguments.length === 6 test('test put()/get()/del() with ' + type, function (t) { db.put(key, value, function (err) { t.error(err) db.get(key, function (err, _value) { t.error(err, 'no error, has key/value for `' + type + '`') + let result + if (!testCommon.encodings) { t.ok(Buffer.isBuffer(_value), 'is a Buffer') - var result = _value + result = _value } else { t.is(typeof _value, 'string', 'is a string') result = _value @@ -76,7 +79,7 @@ function makePutGetDelSuccessfulTest (test, testCommon, type, key, value, expect db.del(key, function (err) { t.error(err, 'no error, deleted key/value for `' + type + '`') - var async = false + let async = false db.get(key, function (err, value) { t.ok(err, 'entry properly deleted') diff --git a/test/put-test.js b/test/put-test.js index 8e4aad83..ce898a5d 100644 --- a/test/put-test.js +++ b/test/put-test.js @@ -1,5 +1,8 @@ -var db -var isTypedArray = require('./util').isTypedArray +'use strict' + +const isTypedArray = require('./util').isTypedArray + +let db exports.setUp = function (test, testCommon) { test('setUp common', testCommon.setUp) @@ -48,11 +51,11 @@ exports.args = function (test, testCommon) { testCommon.serialize && test('test _serialize object', function (t) { t.plan(3) - var db = testCommon.factory() + const db = testCommon.factory() db._put = function (key, value, opts, callback) { t.ok(key) t.ok(value) - process.nextTick(callback) + this._nextTick(callback) } db.put({}, {}, function (err, val) { t.error(err) @@ -61,12 +64,12 @@ exports.args = function (test, testCommon) { testCommon.serialize && test('test custom _serialize*', function (t) { t.plan(4) - var db = testCommon.factory() + const db = testCommon.factory() db._serializeKey = db._serializeValue = function (data) { return data } db._put = function (key, value, options, callback) { t.deepEqual(key, { foo: 'bar' }) t.deepEqual(value, { beep: 'boop' }) - process.nextTick(callback) + this._nextTick(callback) } db.open(function () { db.put({ foo: 'bar' }, { beep: 'boop' }, function (err) { @@ -83,7 +86,7 @@ exports.put = function (test, testCommon) { t.error(err) db.get('foo', function (err, value) { t.error(err) - var result = value.toString() + let result = value.toString() if (isTypedArray(value)) { result = String.fromCharCode.apply(null, new Uint16Array(value)) } diff --git a/test/self.js b/test/self.js index 8dfc6255..3302f444 100644 --- a/test/self.js +++ b/test/self.js @@ -1,13 +1,13 @@ 'use strict' -var test = require('tape') -var sinon = require('sinon') -var inherits = require('util').inherits -var AbstractLevelDOWN = require('../').AbstractLevelDOWN -var AbstractIterator = require('../').AbstractIterator -var AbstractChainedBatch = require('../').AbstractChainedBatch - -var testCommon = require('./common')({ +const test = require('tape') +const sinon = require('sinon') +const inherits = require('util').inherits +const AbstractLevelDOWN = require('../').AbstractLevelDOWN +const AbstractIterator = require('../').AbstractIterator +const AbstractChainedBatch = require('../').AbstractChainedBatch + +const testCommon = require('./common')({ test: test, clear: true, factory: function () { @@ -15,8 +15,7 @@ var testCommon = require('./common')({ } }) -var rangeOptions = ['gt', 'gte', 'lt', 'lte'] -var legacyRangeOptions = ['start', 'end'] +const rangeOptions = ['gt', 'gte', 'lt', 'lte'] // Test the suite itself as well as the default implementation, // excluding noop operations that can't pass the test suite. @@ -85,27 +84,74 @@ function implement (ctor, methods) { inherits(Test, ctor) - for (var k in methods) { + for (const k in methods) { Test.prototype[k] = methods[k] } return Test } +// Temporary test for browsers +// Not supported on Safari < 12 and Safari iOS < 12 +test('async generator', async function (t) { + let ended = false + + const end = async () => { + await new Promise((resolve) => setTimeout(resolve, 100)) + ended = true + } + + async function * generator () { + try { + yield 1 + yield 2 + yield 3 + yield 4 + } finally { + // Test that we're always able to cleanup resources + await end() + } + } + + const res = [] + + for await (const x of generator()) { + res.push(x) + if (x === 2) break + } + + t.same(res, [1, 2]) + t.is(ended, true) + + ended = false + + try { + for await (const x of generator()) { + res.push(x) + if (x === 2) throw new Error('userland error') + } + } catch (err) { + t.is(err.message, 'userland error') + } + + t.same(res, [1, 2, 1, 2]) + t.is(ended, true) +}) + /** * Extensibility */ test('test core extensibility', function (t) { - var Test = implement(AbstractLevelDOWN) - var test = new Test() + const Test = implement(AbstractLevelDOWN) + const test = new Test() t.equal(test.status, 'new', 'status is new') t.end() }) test('test key/value serialization', function (t) { - var Test = implement(AbstractLevelDOWN) - var test = new Test() + const Test = implement(AbstractLevelDOWN) + const test = new Test() ;['', {}, null, undefined, Buffer.alloc(0)].forEach(function (v) { t.ok(test._serializeKey(v) === v, '_serializeKey is an identity function') @@ -116,11 +162,11 @@ test('test key/value serialization', function (t) { }) test('test open() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { createIfMissing: true, errorIfExists: false } - var Test = implement(AbstractLevelDOWN, { _open: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { createIfMissing: true, errorIfExists: false } + const Test = implement(AbstractLevelDOWN, { _open: spy }) + const test = new Test('foobar') test.open(expectedCb) @@ -141,10 +187,10 @@ test('test open() extensibility', function (t) { }) test('test close() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var Test = implement(AbstractLevelDOWN, { _close: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const Test = implement(AbstractLevelDOWN, { _close: spy }) + const test = new Test('foobar') test.close(expectedCb) @@ -155,12 +201,12 @@ test('test close() extensibility', function (t) { }) test('test get() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { asBuffer: true } - var expectedKey = 'a key' - var Test = implement(AbstractLevelDOWN, { _get: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { asBuffer: true } + const expectedKey = 'a key' + const Test = implement(AbstractLevelDOWN, { _get: spy }) + const test = new Test('foobar') test.get(expectedKey, expectedCb) @@ -185,12 +231,12 @@ test('test get() extensibility', function (t) { }) test('test del() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { options: 1 } - var expectedKey = 'a key' - var Test = implement(AbstractLevelDOWN, { _del: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { options: 1 } + const expectedKey = 'a key' + const Test = implement(AbstractLevelDOWN, { _del: spy }) + const test = new Test('foobar') test.del(expectedKey, expectedCb) @@ -213,13 +259,13 @@ test('test del() extensibility', function (t) { }) test('test put() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { options: 1 } - var expectedKey = 'a key' - var expectedValue = 'a value' - var Test = implement(AbstractLevelDOWN, { _put: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { options: 1 } + const expectedKey = 'a key' + const expectedValue = 'a value' + const Test = implement(AbstractLevelDOWN, { _put: spy }) + const test = new Test('foobar') test.put(expectedKey, expectedValue, expectedCb) @@ -244,15 +290,15 @@ test('test put() extensibility', function (t) { }) test('test batch([]) (array-form) extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { options: 1 } - var expectedArray = [ + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { options: 1 } + const expectedArray = [ { type: 'put', key: '1', value: '1' }, { type: 'del', key: '2' } ] - var Test = implement(AbstractLevelDOWN, { _batch: spy }) - var test = new Test('foobar') + const Test = implement(AbstractLevelDOWN, { _batch: spy }) + const test = new Test('foobar') test.batch(expectedArray, expectedCb) @@ -284,10 +330,10 @@ test('test batch([]) (array-form) extensibility', function (t) { }) test('test batch([]) (array-form) with empty array is asynchronous', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { _batch: spy }) - var test = new Test() - var async = false + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy }) + const test = new Test() + let async = false test.batch([], function (err) { t.ifError(err, 'no error') @@ -302,11 +348,11 @@ test('test batch([]) (array-form) with empty array is asynchronous', function (t }) test('test chained batch() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var expectedOptions = { options: 1 } - var Test = implement(AbstractLevelDOWN, { _batch: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const expectedCb = function () {} + const expectedOptions = { options: 1 } + const Test = implement(AbstractLevelDOWN, { _batch: spy }) + const test = new Test('foobar') test.batch().put('foo', 'bar').del('bang').write(expectedCb) @@ -319,14 +365,14 @@ test('test chained batch() extensibility', function (t) { t.deepEqual(spy.getCall(0).args[1], {}, 'got expected options argument') t.equal(spy.getCall(0).args[2], expectedCb, 'got expected callback argument') - test.batch().put('foo', 'bar').del('bang').write(expectedOptions, expectedCb) + test.batch().put('foo', 'bar', expectedOptions).del('bang', expectedOptions).write(expectedOptions, expectedCb) t.equal(spy.callCount, 2, 'got _batch() call') t.equal(spy.getCall(1).thisValue, test, '`this` on _batch() was correct') t.equal(spy.getCall(1).args.length, 3, 'got three arguments') t.equal(spy.getCall(1).args[0].length, 2, 'got expected array argument') - t.deepEqual(spy.getCall(1).args[0][0], { type: 'put', key: 'foo', value: 'bar' }, 'got expected array argument[0]') - t.deepEqual(spy.getCall(1).args[0][1], { type: 'del', key: 'bang' }, 'got expected array argument[1]') + t.deepEqual(spy.getCall(1).args[0][0], { type: 'put', key: 'foo', value: 'bar', options: 1 }, 'got expected array argument[0]') + t.deepEqual(spy.getCall(1).args[0][1], { type: 'del', key: 'bang', options: 1 }, 'got expected array argument[1]') t.deepEqual(spy.getCall(1).args[1], expectedOptions, 'got expected options argument') t.equal(spy.getCall(1).args[2], expectedCb, 'got expected callback argument') @@ -334,9 +380,9 @@ test('test chained batch() extensibility', function (t) { }) test('test chained batch() with no operations is asynchronous', function (t) { - var Test = implement(AbstractLevelDOWN, {}) - var test = new Test() - var async = false + const Test = implement(AbstractLevelDOWN, {}) + const test = new Test() + let async = false test.batch().write(function (err) { t.ifError(err, 'no error') @@ -348,9 +394,9 @@ test('test chained batch() with no operations is asynchronous', function (t) { }) test('test chained batch() (custom _chainedBatch) extensibility', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { _chainedBatch: spy }) - var test = new Test('foobar') + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _chainedBatch: spy }) + const test = new Test('foobar') test.batch() @@ -366,9 +412,9 @@ test('test chained batch() (custom _chainedBatch) extensibility', function (t) { }) test('test AbstractChainedBatch extensibility', function (t) { - var Test = implement(AbstractChainedBatch) - var db = {} - var test = new Test(db) + const Test = implement(AbstractChainedBatch) + const db = {} + const test = new Test(db) t.ok(test.db === db, 'instance has db reference') t.end() }) @@ -376,7 +422,7 @@ test('test AbstractChainedBatch extensibility', function (t) { test('test AbstractChainedBatch expects a db', function (t) { t.plan(1) - var Test = implement(AbstractChainedBatch) + const Test = implement(AbstractChainedBatch) try { Test() @@ -386,10 +432,10 @@ test('test AbstractChainedBatch expects a db', function (t) { }) test('test AbstractChainedBatch#write() extensibility', function (t) { - var spy = sinon.spy() - var spycb = sinon.spy() - var Test = implement(AbstractChainedBatch, { _write: spy }) - var test = new Test({ test: true }) + const spy = sinon.spy() + const spycb = sinon.spy() + const Test = implement(AbstractChainedBatch, { _write: spy }) + const test = new Test({ test: true }) test.write(spycb) @@ -406,9 +452,9 @@ test('test AbstractChainedBatch#write() extensibility', function (t) { }) test('test AbstractChainedBatch#write() extensibility with null options', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractChainedBatch, { _write: spy }) - var test = new Test({ test: true }) + const spy = sinon.spy() + const Test = implement(AbstractChainedBatch, { _write: spy }) + const test = new Test({ test: true }) test.write(null, function () {}) @@ -418,9 +464,9 @@ test('test AbstractChainedBatch#write() extensibility with null options', functi }) test('test AbstractChainedBatch#write() extensibility with options', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractChainedBatch, { _write: spy }) - var test = new Test({ test: true }) + const spy = sinon.spy() + const Test = implement(AbstractChainedBatch, { _write: spy }) + const test = new Test({ test: true }) test.write({ test: true }, function () {}) @@ -430,42 +476,44 @@ test('test AbstractChainedBatch#write() extensibility with options', function (t }) test('test AbstractChainedBatch#put() extensibility', function (t) { - var spy = sinon.spy() - var expectedKey = 'key' - var expectedValue = 'value' - var Test = implement(AbstractChainedBatch, { _put: spy }) - var test = new Test(testCommon.factory()) - var returnValue = test.put(expectedKey, expectedValue) + const spy = sinon.spy() + const expectedKey = 'key' + const expectedValue = 'value' + const Test = implement(AbstractChainedBatch, { _put: spy }) + const test = new Test(testCommon.factory()) + const returnValue = test.put(expectedKey, expectedValue) t.equal(spy.callCount, 1, 'got _put call') t.equal(spy.getCall(0).thisValue, test, '`this` on _put() was correct') - t.equal(spy.getCall(0).args.length, 2, 'got two arguments') + t.equal(spy.getCall(0).args.length, 3, 'got 3 arguments') t.equal(spy.getCall(0).args[0], expectedKey, 'got expected key argument') t.equal(spy.getCall(0).args[1], expectedValue, 'got expected value argument') + t.same(spy.getCall(0).args[2], {}, 'got expected options argument') t.equal(returnValue, test, 'get expected return value') t.end() }) test('test AbstractChainedBatch#del() extensibility', function (t) { - var spy = sinon.spy() - var expectedKey = 'key' - var Test = implement(AbstractChainedBatch, { _del: spy }) - var test = new Test(testCommon.factory()) - var returnValue = test.del(expectedKey) + const spy = sinon.spy() + const expectedKey = 'key' + const Test = implement(AbstractChainedBatch, { _del: spy }) + const test = new Test(testCommon.factory()) + const returnValue = test.del(expectedKey) t.equal(spy.callCount, 1, 'got _del call') t.equal(spy.getCall(0).thisValue, test, '`this` on _del() was correct') - t.equal(spy.getCall(0).args.length, 1, 'got one argument') + t.equal(spy.getCall(0).args.length, 2, 'got 2 arguments') t.equal(spy.getCall(0).args[0], expectedKey, 'got expected key argument') + t.same(spy.getCall(0).args[1], {}, 'got expected options argument') t.equal(returnValue, test, 'get expected return value') t.end() }) test('test AbstractChainedBatch#clear() extensibility', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractChainedBatch, { _clear: spy }) - var test = new Test(testCommon.factory()) - var returnValue = test.clear() + const spy = sinon.spy() + const Test = implement(AbstractChainedBatch, { _clear: spy }) + const test = new Test(testCommon.factory()) + const returnValue = test.clear() t.equal(spy.callCount, 1, 'got _clear call') t.equal(spy.getCall(0).thisValue, test, '`this` on _clear() was correct') @@ -475,8 +523,8 @@ test('test AbstractChainedBatch#clear() extensibility', function (t) { }) test('test iterator() extensibility', function (t) { - var spy = sinon.spy() - var expectedOptions = { + const spy = sinon.spy() + const expectedOptions = { options: 1, reverse: false, keys: true, @@ -485,8 +533,8 @@ test('test iterator() extensibility', function (t) { keyAsBuffer: true, valueAsBuffer: true } - var Test = implement(AbstractLevelDOWN, { _iterator: spy }) - var test = new Test('foobar') + const Test = implement(AbstractLevelDOWN, { _iterator: spy }) + const test = new Test('foobar') test.iterator({ options: 1 }) @@ -498,18 +546,18 @@ test('test iterator() extensibility', function (t) { }) test('test AbstractIterator extensibility', function (t) { - var Test = implement(AbstractIterator) - var db = {} - var test = new Test(db) + const Test = implement(AbstractIterator) + const db = {} + const test = new Test(db) t.ok(test.db === db, 'instance has db reference') t.end() }) test('test AbstractIterator#next() extensibility', function (t) { - var spy = sinon.spy() - var spycb = sinon.spy() - var Test = implement(AbstractIterator, { _next: spy }) - var test = new Test({}) + const spy = sinon.spy() + const spycb = sinon.spy() + const Test = implement(AbstractIterator, { _next: spy }) + const test = new Test({}) test.next(spycb) @@ -525,10 +573,10 @@ test('test AbstractIterator#next() extensibility', function (t) { }) test('test AbstractIterator#end() extensibility', function (t) { - var spy = sinon.spy() - var expectedCb = function () {} - var Test = implement(AbstractIterator, { _end: spy }) - var test = new Test({}) + const spy = sinon.spy() + const expectedCb = function () {} + const Test = implement(AbstractIterator, { _end: spy }) + const test = new Test({}) test.end(expectedCb) @@ -540,10 +588,10 @@ test('test AbstractIterator#end() extensibility', function (t) { }) test('test clear() extensibility', function (t) { - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { _clear: spy }) - var db = new Test() - var callback = function () {} + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _clear: spy }) + const db = new Test() + const callback = function () {} call([callback], { reverse: false, limit: -1 }) call([null, callback], { reverse: false, limit: -1 }) @@ -571,8 +619,8 @@ test('test clear() extensibility', function (t) { test('test serialization extensibility (put)', function (t) { t.plan(5) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _put: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -585,7 +633,7 @@ test('test serialization extensibility (put)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.put('no', 'nope', function () {}) t.equal(spy.callCount, 1, 'got _put() call') @@ -596,8 +644,8 @@ test('test serialization extensibility (put)', function (t) { test('test serialization extensibility (del)', function (t) { t.plan(3) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _del: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -608,7 +656,7 @@ test('test serialization extensibility (del)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.del('no', function () {}) t.equal(spy.callCount, 1, 'got _del() call') @@ -620,8 +668,8 @@ test('test serialization extensibility (del)', function (t) { test('test serialization extensibility (batch array put)', function (t) { t.plan(5) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -633,7 +681,7 @@ test('test serialization extensibility (batch array put)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.batch([{ type: 'put', key: 'no', value: 'nope' }], function () {}) t.equal(spy.callCount, 1, 'got _batch() call') @@ -644,8 +692,8 @@ test('test serialization extensibility (batch array put)', function (t) { test('test serialization extensibility (batch chain put)', function (t) { t.plan(5) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -657,7 +705,7 @@ test('test serialization extensibility (batch chain put)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.batch().put('no', 'nope').write(function () {}) t.equal(spy.callCount, 1, 'got _batch() call') @@ -668,8 +716,8 @@ test('test serialization extensibility (batch chain put)', function (t) { test('test serialization extensibility (batch array del)', function (t) { t.plan(3) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -680,7 +728,7 @@ test('test serialization extensibility (batch array del)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.batch([{ type: 'del', key: 'no' }], function () {}) t.equal(spy.callCount, 1, 'got _batch() call') @@ -690,8 +738,8 @@ test('test serialization extensibility (batch array del)', function (t) { test('test serialization extensibility (batch chain del)', function (t) { t.plan(3) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -702,7 +750,7 @@ test('test serialization extensibility (batch chain del)', function (t) { } }) - var test = new Test('foobar') + const test = new Test('foobar') test.batch().del('no').write(function () {}) t.equal(spy.callCount, 1, 'got _batch() call') @@ -712,8 +760,8 @@ test('test serialization extensibility (batch chain del)', function (t) { test('test serialization extensibility (batch array is not mutated)', function (t) { t.plan(7) - var spy = sinon.spy() - var Test = implement(AbstractLevelDOWN, { + const spy = sinon.spy() + const Test = implement(AbstractLevelDOWN, { _batch: spy, _serializeKey: function (key) { t.equal(key, 'no') @@ -725,8 +773,8 @@ test('test serialization extensibility (batch array is not mutated)', function ( } }) - var test = new Test('foobar') - var op = { type: 'put', key: 'no', value: 'nope' } + const test = new Test('foobar') + const op = { type: 'put', key: 'no', value: 'nope' } test.batch([op], function () {}) @@ -763,17 +811,17 @@ test('test serialization extensibility (iterator range options)', function (t) { inherits(Iterator, AbstractIterator) - var test = new Test() + const test = new Test() test.iterator({ gt: 'input' }) }) test('test serialization extensibility (iterator seek)', function (t) { t.plan(3) - var spy = sinon.spy() - var TestIterator = implement(AbstractIterator, { _seek: spy }) + const spy = sinon.spy() + const TestIterator = implement(AbstractIterator, { _seek: spy }) - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _iterator: function () { return new TestIterator(this) }, @@ -783,8 +831,8 @@ test('test serialization extensibility (iterator seek)', function (t) { } }) - var test = new Test('foobar') - var it = test.iterator() + const test = new Test('foobar') + const it = test.iterator() it.seek('target') @@ -796,7 +844,7 @@ test('test serialization extensibility (clear range options)', function (t) { t.plan(rangeOptions.length * 2) rangeOptions.forEach(function (key) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _serializeKey: function (key) { t.is(key, 'input') return 'output' @@ -806,8 +854,8 @@ test('test serialization extensibility (clear range options)', function (t) { } }) - var db = new Test() - var options = {} + const db = new Test() + const options = {} options[key] = 'input' db.clear(options, function () {}) @@ -815,12 +863,12 @@ test('test serialization extensibility (clear range options)', function (t) { }) test('clear() does not delete empty or nullish range options', function (t) { - var rangeValues = [Buffer.alloc(0), '', null, undefined] + const rangeValues = [Buffer.alloc(0), '', null, undefined] t.plan(rangeOptions.length * rangeValues.length) rangeValues.forEach(function (value) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _clear: function (options, callback) { rangeOptions.forEach(function (key) { t.ok(key in options, key + ' option should not be deleted') @@ -828,8 +876,8 @@ test('clear() does not delete empty or nullish range options', function (t) { } }) - var db = new Test() - var options = {} + const db = new Test() + const options = {} rangeOptions.forEach(function (key) { options[key] = value @@ -843,8 +891,8 @@ test('.status', function (t) { t.plan(5) t.test('empty prototype', function (t) { - var Test = implement(AbstractLevelDOWN) - var test = new Test('foobar') + const Test = implement(AbstractLevelDOWN) + const test = new Test('foobar') t.equal(test.status, 'new') @@ -861,13 +909,13 @@ test('.status', function (t) { }) t.test('open error', function (t) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _open: function (options, cb) { cb(new Error()) } }) - var test = new Test('foobar') + const test = new Test('foobar') test.open(function (err) { t.ok(err) @@ -877,13 +925,13 @@ test('.status', function (t) { }) t.test('close error', function (t) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _close: function (cb) { cb(new Error()) } }) - var test = new Test('foobar') + const test = new Test('foobar') test.open(function () { test.close(function (err) { t.ok(err) @@ -894,13 +942,13 @@ test('.status', function (t) { }) t.test('open', function (t) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _open: function (options, cb) { - process.nextTick(cb) + this._nextTick(cb) } }) - var test = new Test('foobar') + const test = new Test('foobar') test.open(function (err) { t.error(err) t.equal(test.status, 'open') @@ -910,13 +958,13 @@ test('.status', function (t) { }) t.test('close', function (t) { - var Test = implement(AbstractLevelDOWN, { + const Test = implement(AbstractLevelDOWN, { _close: function (cb) { - process.nextTick(cb) + this._nextTick(cb) } }) - var test = new Test('foobar') + const test = new Test('foobar') test.open(function (err) { t.error(err) test.close(function (err) { @@ -930,11 +978,11 @@ test('.status', function (t) { }) test('_setupIteratorOptions', function (t) { - var keys = legacyRangeOptions.concat(rangeOptions) - var db = new AbstractLevelDOWN() + const keys = rangeOptions.slice() + const db = new AbstractLevelDOWN() function setupOptions (constrFn) { - var options = {} + const options = {} keys.forEach(function (key) { options[key] = constrFn() }) @@ -948,7 +996,7 @@ test('_setupIteratorOptions', function (t) { t.end() } - t.plan(6) + t.plan(7) t.test('default options', function (t) { t.same(db._setupIteratorOptions(), { @@ -982,7 +1030,7 @@ test('_setupIteratorOptions', function (t) { }) t.test('does not delete empty buffers', function (t) { - var options = setupOptions(function () { return Buffer.from('') }) + const options = setupOptions(function () { return Buffer.from('') }) keys.forEach(function (key) { t.is(Buffer.isBuffer(options[key]), true, 'should be buffer') t.is(options[key].length, 0, 'should be empty') @@ -991,7 +1039,7 @@ test('_setupIteratorOptions', function (t) { }) t.test('does not delete empty strings', function (t) { - var options = setupOptions(function () { return '' }) + const options = setupOptions(function () { return '' }) keys.forEach(function (key) { t.is(typeof options[key], 'string', 'should be string') t.is(options[key].length, 0, 'should be empty') @@ -1000,7 +1048,7 @@ test('_setupIteratorOptions', function (t) { }) t.test('does not delete null', function (t) { - var options = setupOptions(function () { return null }) + const options = setupOptions(function () { return null }) keys.forEach(function (key) { t.is(options[key], null, 'should be null') }) @@ -1008,10 +1056,25 @@ test('_setupIteratorOptions', function (t) { }) t.test('does not delete undefined', function (t) { - var options = setupOptions(function () { return undefined }) + const options = setupOptions(function () { return undefined }) keys.forEach(function (key) { t.is(options[key], undefined, 'should be undefined') }) verifyOptions(t, db._setupIteratorOptions(options)) }) + + t.test('rejects legacy range options', function (t) { + t.plan(2) + + for (const key of ['start', 'end']) { + const options = {} + options[key] = 'x' + + try { + db._setupIteratorOptions(options) + } catch (err) { + t.is(err.message, 'Legacy range options ("start" and "end") have been removed') + } + } + }) }) diff --git a/test/util.js b/test/util.js index db656260..5d833475 100644 --- a/test/util.js +++ b/test/util.js @@ -1,4 +1,6 @@ -var nfre = /NotFound/i +'use strict' + +const nfre = /NotFound/i exports.verifyNotFoundError = function verifyNotFoundError (err) { return nfre.test(err.message) || nfre.test(err.name)