From ab7c1a599dc6b9fe56b8255e7c1a34e4e7c4d9fd Mon Sep 17 00:00:00 2001 From: Lars-Magnus Skog Date: Wed, 11 Jul 2018 23:35:41 +0200 Subject: [PATCH 01/13] Create next branch which targets master branch of abstract-leveldown --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56b01486..a1e6f874 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "~5.0.0", + "abstract-leveldown": "level/abstract-leveldown#master", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", From e1ac18dbbc6699c1eddb3bd70ce5317386b915e8 Mon Sep 17 00:00:00 2001 From: Lars-Magnus Skog Date: Fri, 13 Jul 2018 16:58:16 +0200 Subject: [PATCH 02/13] Location was removed from abstract-leveldown (#494) * Location was removed from abstract-leveldown * handle location in LevelDOWN constructor * pass a factory function to abstract tests * use tempy and remove cleanup code * Add type check for location in constructor --- leveldown.js | 8 ++++- package.json | 2 ++ test/approximate-size-test.js | 7 ++--- test/batch-test.js | 6 ++-- test/chained-batch-test.js | 6 ++-- test/close-test.js | 23 ++++----------- test/common.js | 9 ++++++ test/compact-range-test.js | 5 ++-- test/compression-test.js | 15 ++++------ test/del-test.js | 6 ++-- test/destroy-test.js | 10 ++++--- test/get-test.js | 6 ++-- test/getproperty-test.js | 5 ++-- test/iterator-gc-test.js | 8 ++--- test/iterator-range-test.js | 6 ++-- test/iterator-recursion-test.js | 5 ++-- test/iterator-test.js | 6 ++-- test/leak-tester-batch.js | 12 ++++---- test/leak-tester.js | 12 ++++---- test/leveldown-test.js | 14 +++++++-- test/make.js | 52 +++++++++++++-------------------- test/open-test.js | 6 ++-- test/put-get-del-test.js | 6 ++-- test/put-test.js | 6 ++-- test/repair-test.js | 3 +- test/stack-blower.js | 31 +++++++++----------- 26 files changed, 132 insertions(+), 143 deletions(-) create mode 100644 test/common.js diff --git a/leveldown.js b/leveldown.js index 5bf0169c..91353932 100644 --- a/leveldown.js +++ b/leveldown.js @@ -9,7 +9,13 @@ function LevelDOWN (location) { return new LevelDOWN(location) } - AbstractLevelDOWN.call(this, location) + if (typeof location !== 'string') { + throw new Error('constructor requires a location string argument') + } + + AbstractLevelDOWN.call(this) + + this.location = location this.binding = binding(location) } diff --git a/package.json b/package.json index a1e6f874..e455da3f 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "delayed": "~1.0.1", "du": "~0.1.0", "iota-array": "~1.0.0", + "level-concat-iterator": "^2.0.0", "lexicographic-integer": "~1.1.0", "mkfiletree": "~1.0.1", "monotonic-timestamp": "~0.0.8", @@ -39,6 +40,7 @@ "slump": "~2.0.0", "standard": "^12.0.0", "tape": "^4.5.1", + "tempy": "^0.2.1", "uuid": "^3.2.1", "verify-travis-appveyor": "^3.0.0" }, diff --git a/test/approximate-size-test.js b/test/approximate-size-test.js index 93b859b7..06dced35 100644 --- a/test/approximate-size-test.js +++ b/test/approximate-size-test.js @@ -1,13 +1,12 @@ const test = require('tape') -const leveldown = require('..') -const testCommon = require('abstract-leveldown/testCommon') +const testCommon = require('./common') var db test('setUp common for approximate size', testCommon.setUp) test('setUp db', function (t) { - db = leveldown(testCommon.location()) + db = testCommon.factory() db.open(t.end.bind(t)) }) @@ -67,7 +66,7 @@ test('test 1-arg + callback approximateSize() throws', function (t) { test('test custom _serialize*', function (t) { t.plan(4) - var db = leveldown(testCommon.location()) + var db = testCommon.factory() db._serializeKey = function (data) { return data } db.approximateSize = function (start, end, callback) { t.deepEqual(start, { foo: 'bar' }) diff --git a/test/batch-test.js b/test/batch-test.js index 2ac3d9fa..4594c48a 100644 --- a/test/batch-test.js +++ b/test/batch-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/batch-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/batch-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/chained-batch-test.js b/test/chained-batch-test.js index 56cf58a0..a8adb35d 100644 --- a/test/chained-batch-test.js +++ b/test/chained-batch-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/chained-batch-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/chained-batch-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/close-test.js b/test/close-test.js index f0e81ac4..5e873e22 100644 --- a/test/close-test.js +++ b/test/close-test.js @@ -1,22 +1,9 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/close-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/close-test') -module.exports.setUp = function () { - test('setUp', testCommon.setUp) -} +test('setUp', testCommon.setUp) -module.exports.close = abstract.close +abstract.close(testCommon.factory, test, testCommon) -module.exports.tearDown = function () { - test('tearDown', testCommon.tearDown) -} - -module.exports.all = function (leveldown) { - module.exports.setUp() - module.exports.close(leveldown, test, testCommon) - module.exports.tearDown() -} - -module.exports.all(leveldown) +test('tearDown', testCommon.tearDown) diff --git a/test/common.js b/test/common.js new file mode 100644 index 00000000..d905eb6f --- /dev/null +++ b/test/common.js @@ -0,0 +1,9 @@ +const testCommon = require('abstract-leveldown/test/common') +const tempy = require('tempy') +const leveldown = require('..') + +testCommon.factory = function () { + return leveldown(tempy.directory()) +} + +module.exports = testCommon diff --git a/test/compact-range-test.js b/test/compact-range-test.js index c13fa93d..2cefb9e0 100644 --- a/test/compact-range-test.js +++ b/test/compact-range-test.js @@ -1,13 +1,12 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') +const testCommon = require('./common') let db test('setUp common', testCommon.setUp) test('setUp db', function (t) { - db = leveldown(testCommon.location()) + db = testCommon.factory() db.open(t.end.bind(t)) }) diff --git a/test/compression-test.js b/test/compression-test.js index 8b9f9cb7..48548b27 100644 --- a/test/compression-test.js +++ b/test/compression-test.js @@ -1,12 +1,7 @@ -/* Copyright (c) 2012-2017 LevelUP contributors - * See list at - * MIT License - */ - const async = require('async') const du = require('du') const delayed = require('delayed') -const common = require('abstract-leveldown/testCommon') +const testCommon = require('./common') const leveldown = require('..') const test = require('tape') @@ -46,10 +41,10 @@ const cycle = function (db, compression, t, callback) { } test('Compression', function (t) { - t.test('set up', common.setUp) + t.test('set up', testCommon.setUp) t.test('test data is compressed by default (db.put())', function (t) { - var db = leveldown(common.location()) + var db = testCommon.factory() db.open(function (err) { t.error(err) async.forEach( @@ -63,7 +58,7 @@ test('Compression', function (t) { }) t.test('test data is not compressed with compression=false on open() (db.put())', function (t) { - var db = leveldown(common.location()) + var db = testCommon.factory() db.open({ compression: false }, function (err) { t.error(err) async.forEach( @@ -77,7 +72,7 @@ test('Compression', function (t) { }) t.test('test data is compressed by default (db.batch())', function (t) { - var db = leveldown(common.location()) + var db = testCommon.factory() db.open(function (err) { t.error(err) db.batch( diff --git a/test/del-test.js b/test/del-test.js index 18253113..8ca70133 100644 --- a/test/del-test.js +++ b/test/del-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/del-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/del-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/destroy-test.js b/test/destroy-test.js index e0cc2af8..15612ff6 100644 --- a/test/destroy-test.js +++ b/test/destroy-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') +const tempy = require('tempy') const fs = require('fs') const path = require('path') const mkfiletree = require('mkfiletree') @@ -27,7 +27,7 @@ test('test callback-less, 1-arg, destroy() throws', function (t) { test('test destroy non-existent directory', function (t) { t.plan(4) - var location = testCommon.location() + var location = tempy.directory() var parent = path.dirname(location) // For symmetry with the opposite test below. @@ -86,7 +86,8 @@ test('test destroy non leveldb directory', function (t) { }) }) -makeTest('test destroy() cleans and removes leveldb-only dir', function (db, t, done, location) { +makeTest('test destroy() cleans and removes leveldb-only dir', function (db, t, done) { + var location = db.location db.close(function (err) { t.ifError(err, 'no close error') @@ -99,7 +100,8 @@ makeTest('test destroy() cleans and removes leveldb-only dir', function (db, t, }) }) -makeTest('test destroy() cleans and removes only leveldb parts of a dir', function (db, t, done, location) { +makeTest('test destroy() cleans and removes only leveldb parts of a dir', function (db, t, done) { + var location = db.location fs.writeFileSync(path.join(location, 'foo'), 'FOO') db.close(function (err) { diff --git a/test/get-test.js b/test/get-test.js index 51977702..50ed52a2 100644 --- a/test/get-test.js +++ b/test/get-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/get-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/get-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/getproperty-test.js b/test/getproperty-test.js index 28ae0dc5..fa072c63 100644 --- a/test/getproperty-test.js +++ b/test/getproperty-test.js @@ -1,13 +1,12 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') +const testCommon = require('./common') let db test('setUp common', testCommon.setUp) test('setUp db', function (t) { - db = leveldown(testCommon.location()) + db = testCommon.factory() db.open(t.end.bind(t)) }) diff --git a/test/iterator-gc-test.js b/test/iterator-gc-test.js index feda357f..51a3dbd0 100644 --- a/test/iterator-gc-test.js +++ b/test/iterator-gc-test.js @@ -1,8 +1,8 @@ 'use strict' const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') +const collectEntries = require('level-concat-iterator') +const testCommon = require('./common') const sourceData = [] for (let i = 0; i < 1e3; i++) { @@ -20,7 +20,7 @@ test('setUp', testCommon.setUp) test('db without ref does not get GCed while iterating', function (t) { t.plan(6) - let db = leveldown(testCommon.location()) + let db = testCommon.factory() db.open(function (err) { t.ifError(err, 'no open error') @@ -50,7 +50,7 @@ test('db without ref does not get GCed while iterating', function (t) { function iterate (it) { // No reference to db here, could be GCed. It shouldn't.. - testCommon.collectEntries(it, function (err, entries) { + collectEntries(it, function (err, entries) { t.ifError(err, 'no iterator error') t.is(entries.length, sourceData.length, 'got data') diff --git a/test/iterator-range-test.js b/test/iterator-range-test.js index fa828e9b..d8595355 100644 --- a/test/iterator-range-test.js +++ b/test/iterator-range-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/iterator-range-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/iterator-range-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/iterator-recursion-test.js b/test/iterator-recursion-test.js index f7677e80..1c799fd2 100644 --- a/test/iterator-recursion-test.js +++ b/test/iterator-recursion-test.js @@ -1,6 +1,5 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') +const testCommon = require('./common') const fork = require('child_process').fork const path = require('path') @@ -43,7 +42,7 @@ test('try to create an iterator with a blown stack', function (t) { }) test('setUp db', function (t) { - db = leveldown(testCommon.location()) + db = testCommon.factory() db.open(function (err) { t.error(err) db.batch(sourceData, t.end.bind(t)) diff --git a/test/iterator-test.js b/test/iterator-test.js index 95723041..0554b76f 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -1,12 +1,12 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/iterator-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/iterator-test') const make = require('./make') const iota = require('iota-array') const lexi = require('lexicographic-integer') const util = require('util') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) make('iterator throws if key is not a string or buffer', function (db, t, done) { var keys = [null, undefined, 1, true, false] diff --git a/test/leak-tester-batch.js b/test/leak-tester-batch.js index 7f27c64b..d57befda 100644 --- a/test/leak-tester-batch.js +++ b/test/leak-tester-batch.js @@ -1,7 +1,7 @@ const BUFFERS = false const CHAINED = false -const leveldown = require('..') +const testCommon = require('./common') const crypto = require('crypto') const assert = require('assert') @@ -72,10 +72,8 @@ var run = CHAINED print() } -leveldown.destroy('./leakydb', function () { - db = leveldown('./leakydb') - db.open({ xcacheSize: 0, xmaxOpenFiles: 10 }, function () { - rssBase = process.memoryUsage().rss - run() - }) +db = testCommon.factory() +db.open({ xcacheSize: 0, xmaxOpenFiles: 10 }, function () { + rssBase = process.memoryUsage().rss + run() }) diff --git a/test/leak-tester.js b/test/leak-tester.js index 1b2afa56..5fd81ae3 100644 --- a/test/leak-tester.js +++ b/test/leak-tester.js @@ -1,6 +1,6 @@ const BUFFERS = false -const leveldown = require('..') +const testCommon = require('./common') const crypto = require('crypto') let putCount = 0 @@ -40,10 +40,8 @@ function run () { } } -leveldown.destroy('./leakydb', function () { - db = leveldown('./leakydb') - db.open({ xcacheSize: 0, xmaxOpenFiles: 10 }, function () { - rssBase = process.memoryUsage().rss - run() - }) +db = testCommon.factory() +db.open({ xcacheSize: 0, xmaxOpenFiles: 10 }, function () { + rssBase = process.memoryUsage().rss + run() }) diff --git a/test/leveldown-test.js b/test/leveldown-test.js index 6bf6c33f..44df42c2 100644 --- a/test/leveldown-test.js +++ b/test/leveldown-test.js @@ -1,5 +1,15 @@ const test = require('tape') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/leveldown-test') const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/leveldown-test') -abstract.args(leveldown, test) +abstract.args(testCommon.factory, test) + +test('test database creation non-string location throws', function (t) { + t.throws( + leveldown.bind(null, {}), + /constructor requires a location string argument/, + 'non-string location leveldown() throws' + ) + t.end() +}) diff --git a/test/make.js b/test/make.js index 1ed47ee4..d50d6397 100644 --- a/test/make.js +++ b/test/make.js @@ -1,40 +1,28 @@ const test = require('tape') -const testCommon = require('abstract-leveldown/testCommon') -const cleanup = testCommon.cleanup -const leveldown = require('..') +const testCommon = require('./common') function makeTest (name, testFn) { test(name, function (t) { - cleanup(function (err) { - t.error(err, 'no error after cleanup') - var location = testCommon.location() - var db = leveldown(location) - var done = function (close) { - if (close === false) { - cleanup(function (err) { - t.error(err, 'no error after cleanup') - t.end() - }) - return - } - db.close(function (err) { - t.error(err, 'no error from close()') - cleanup(function (err) { - t.error(err, 'no error after cleanup') - t.end() - }) - }) + var db = testCommon.factory() + var done = function (close) { + if (close === false) { + t.end() + return } - db.open(function (err) { - t.error(err, 'no error from open()') - db.batch([ - { type: 'put', key: 'one', value: '1' }, - { type: 'put', key: 'two', value: '2' }, - { type: 'put', key: 'three', value: '3' } - ], function (err) { - t.error(err, 'no error from batch()') - testFn(db, t, done, location) - }) + db.close(function (err) { + t.error(err, 'no error from close()') + t.end() + }) + } + db.open(function (err) { + t.error(err, 'no error from open()') + db.batch([ + { type: 'put', key: 'one', value: '1' }, + { type: 'put', key: 'two', value: '2' }, + { type: 'put', key: 'three', value: '3' } + ], function (err) { + t.error(err, 'no error from batch()') + testFn(db, t, done) }) }) }) diff --git a/test/open-test.js b/test/open-test.js index 0c9ce201..7d16bc89 100644 --- a/test/open-test.js +++ b/test/open-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/open-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/open-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/put-get-del-test.js b/test/put-get-del-test.js index 0e868abc..1317688b 100644 --- a/test/put-get-del-test.js +++ b/test/put-get-del-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/put-get-del-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/put-get-del-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/put-test.js b/test/put-test.js index c74c69bf..b7983230 100644 --- a/test/put-test.js +++ b/test/put-test.js @@ -1,5 +1,5 @@ const test = require('tape') -const leveldown = require('..') -const abstract = require('abstract-leveldown/abstract/put-test') +const testCommon = require('./common') +const abstract = require('abstract-leveldown/test/put-test') -abstract.all(leveldown, test) +abstract.all(testCommon.factory, test) diff --git a/test/repair-test.js b/test/repair-test.js index 126d49a7..aa7ad34b 100644 --- a/test/repair-test.js +++ b/test/repair-test.js @@ -31,7 +31,8 @@ test('test repair non-existent directory returns error', function (t) { }) // a proxy indicator that RepairDB is being called and doing its thing -makeTest('test repair() compacts', function (db, t, done, location) { +makeTest('test repair() compacts', function (db, t, done) { + var location = db.location db.close(function (err) { t.notOk(err, 'no error') var files = fs.readdirSync(location) diff --git a/test/stack-blower.js b/test/stack-blower.js index 2c2e157e..9d464b99 100644 --- a/test/stack-blower.js +++ b/test/stack-blower.js @@ -5,26 +5,23 @@ * iterator-recursion-test.js. To prevent tap from trying to run this test * directly, we check for a command-line argument. */ -const testCommon = require('abstract-leveldown/testCommon') -const leveldown = require('..') +const testCommon = require('./common') if (process.argv[2] === 'run') { - testCommon.cleanup(function () { - var db = leveldown(testCommon.location()) - var depth = 0 + var db = testCommon.factory() + var depth = 0 - db.open(function () { - function recurse () { - db.iterator({ start: '0' }) - depth++ - recurse() - } + db.open(function () { + function recurse () { + db.iterator({ start: '0' }) + depth++ + recurse() + } - try { - recurse() - } catch (e) { - process.send('Catchable error at depth ' + depth) - } - }) + try { + recurse() + } catch (e) { + process.send('Catchable error at depth ' + depth) + } }) } From 52b0777e9cad435cea7582cebf9de012dcfb5831 Mon Sep 17 00:00:00 2001 From: Lars-Magnus Skog Date: Fri, 13 Jul 2018 19:59:03 +0200 Subject: [PATCH 03/13] Abstract tests single function (#495) * Target abstract-leveldown#ffba12f * Use single test function from abstract-leveldown * Target abstract-leveldown#d7411bb * Options is actually now passed as options from abstract-leveldown and not a function --- chained-batch.js | 2 +- package.json | 2 +- test/abstract-leveldown-test.js | 1 + test/batch-test.js | 5 ----- test/chained-batch-test.js | 5 ----- test/close-test.js | 9 --------- test/common.js | 13 +++++++------ test/del-test.js | 5 ----- test/get-test.js | 5 ----- test/iterator-range-test.js | 5 ----- test/iterator-test.js | 5 ----- test/leveldown-test.js | 4 ---- test/open-test.js | 5 ----- test/put-get-del-test.js | 5 ----- test/put-test.js | 5 ----- 15 files changed, 10 insertions(+), 66 deletions(-) create mode 100644 test/abstract-leveldown-test.js delete mode 100644 test/batch-test.js delete mode 100644 test/chained-batch-test.js delete mode 100644 test/close-test.js delete mode 100644 test/del-test.js delete mode 100644 test/get-test.js delete mode 100644 test/iterator-range-test.js delete mode 100644 test/open-test.js delete mode 100644 test/put-get-del-test.js delete mode 100644 test/put-test.js diff --git a/chained-batch.js b/chained-batch.js index fadc76d4..0b917672 100644 --- a/chained-batch.js +++ b/chained-batch.js @@ -19,7 +19,7 @@ ChainedBatch.prototype._clear = function (key) { } ChainedBatch.prototype._write = function (options, callback) { - this.binding.write(options, callback) + this.binding.write(callback) } util.inherits(ChainedBatch, AbstractChainedBatch) diff --git a/package.json b/package.json index e455da3f..d6a64b5c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "level/abstract-leveldown#master", + "abstract-leveldown": "level/abstract-leveldown#d7411bb", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", diff --git a/test/abstract-leveldown-test.js b/test/abstract-leveldown-test.js new file mode 100644 index 00000000..12888ea0 --- /dev/null +++ b/test/abstract-leveldown-test.js @@ -0,0 +1 @@ +require('abstract-leveldown/test')(require('./common')) diff --git a/test/batch-test.js b/test/batch-test.js deleted file mode 100644 index 4594c48a..00000000 --- a/test/batch-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/batch-test') - -abstract.all(testCommon.factory, test) diff --git a/test/chained-batch-test.js b/test/chained-batch-test.js deleted file mode 100644 index a8adb35d..00000000 --- a/test/chained-batch-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/chained-batch-test') - -abstract.all(testCommon.factory, test) diff --git a/test/close-test.js b/test/close-test.js deleted file mode 100644 index 5e873e22..00000000 --- a/test/close-test.js +++ /dev/null @@ -1,9 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/close-test') - -test('setUp', testCommon.setUp) - -abstract.close(testCommon.factory, test, testCommon) - -test('tearDown', testCommon.tearDown) diff --git a/test/common.js b/test/common.js index d905eb6f..4c55d8b0 100644 --- a/test/common.js +++ b/test/common.js @@ -1,9 +1,10 @@ -const testCommon = require('abstract-leveldown/test/common') +const test = require('tape') const tempy = require('tempy') const leveldown = require('..') -testCommon.factory = function () { - return leveldown(tempy.directory()) -} - -module.exports = testCommon +module.exports = require('abstract-leveldown/test/common')({ + test: test, + factory: function () { + return leveldown(tempy.directory()) + } +}) diff --git a/test/del-test.js b/test/del-test.js deleted file mode 100644 index 8ca70133..00000000 --- a/test/del-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/del-test') - -abstract.all(testCommon.factory, test) diff --git a/test/get-test.js b/test/get-test.js deleted file mode 100644 index 50ed52a2..00000000 --- a/test/get-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/get-test') - -abstract.all(testCommon.factory, test) diff --git a/test/iterator-range-test.js b/test/iterator-range-test.js deleted file mode 100644 index d8595355..00000000 --- a/test/iterator-range-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/iterator-range-test') - -abstract.all(testCommon.factory, test) diff --git a/test/iterator-test.js b/test/iterator-test.js index 0554b76f..6e611ee8 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -1,13 +1,8 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/iterator-test') const make = require('./make') const iota = require('iota-array') const lexi = require('lexicographic-integer') const util = require('util') -abstract.all(testCommon.factory, test) - make('iterator throws if key is not a string or buffer', function (db, t, done) { var keys = [null, undefined, 1, true, false] var pending = keys.length diff --git a/test/leveldown-test.js b/test/leveldown-test.js index 44df42c2..bf002307 100644 --- a/test/leveldown-test.js +++ b/test/leveldown-test.js @@ -1,10 +1,6 @@ const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/leveldown-test') const leveldown = require('..') -abstract.args(testCommon.factory, test) - test('test database creation non-string location throws', function (t) { t.throws( leveldown.bind(null, {}), diff --git a/test/open-test.js b/test/open-test.js deleted file mode 100644 index 7d16bc89..00000000 --- a/test/open-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/open-test') - -abstract.all(testCommon.factory, test) diff --git a/test/put-get-del-test.js b/test/put-get-del-test.js deleted file mode 100644 index 1317688b..00000000 --- a/test/put-get-del-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/put-get-del-test') - -abstract.all(testCommon.factory, test) diff --git a/test/put-test.js b/test/put-test.js deleted file mode 100644 index b7983230..00000000 --- a/test/put-test.js +++ /dev/null @@ -1,5 +0,0 @@ -const test = require('tape') -const testCommon = require('./common') -const abstract = require('abstract-leveldown/test/put-test') - -abstract.all(testCommon.factory, test) From 5745555a6eff837ae135ab8d5eeb57190e03c025 Mon Sep 17 00:00:00 2001 From: Lars-Magnus Skog Date: Sun, 15 Jul 2018 19:28:44 +0200 Subject: [PATCH 04/13] Target abstract-leveldown#51af868 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6a64b5c..3f2c896e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "level/abstract-leveldown#d7411bb", + "abstract-leveldown": "level/abstract-leveldown#51af868", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", From 7b0f6d91c13f7e67ee17799c2a4443675d3d7187 Mon Sep 17 00:00:00 2001 From: Lars-Magnus Skog Date: Sun, 15 Jul 2018 19:34:20 +0200 Subject: [PATCH 05/13] Use suite.common() in test/common.js --- test/common.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/common.js b/test/common.js index 4c55d8b0..14a4a904 100644 --- a/test/common.js +++ b/test/common.js @@ -1,8 +1,9 @@ const test = require('tape') const tempy = require('tempy') const leveldown = require('..') +const suite = require('abstract-leveldown/test') -module.exports = require('abstract-leveldown/test/common')({ +module.exports = suite.common({ test: test, factory: function () { return leveldown(tempy.directory()) From a007051f8a0a5cbf9cb0b13a51d48fd5f039b1d1 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sun, 15 Jul 2018 15:55:27 +0200 Subject: [PATCH 06/13] target Level/abstract-leveldown#0f42686 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3f2c896e..67f5d935 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "level/abstract-leveldown#51af868", + "abstract-leveldown": "github:Level/abstract-leveldown#0f42686", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", From 82cdd77323a252ba4e82700a9bd4b589551e8c74 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sun, 15 Jul 2018 16:38:29 +0200 Subject: [PATCH 07/13] implement _seek instead of seek --- iterator.js | 13 ++----------- test/iterator-test.js | 41 +++++++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/iterator.js b/iterator.js index 9d412e56..1e99a819 100644 --- a/iterator.js +++ b/iterator.js @@ -13,18 +13,9 @@ function Iterator (db, options) { util.inherits(Iterator, AbstractIterator) -Iterator.prototype.seek = function (target) { - if (this._ended) { - throw new Error('cannot call seek() after end()') - } - if (this._nexting) { - throw new Error('cannot call seek() before next() has completed') - } - if (typeof target !== 'string' && !Buffer.isBuffer(target)) { - throw new Error('seek() requires a string or buffer key') - } +Iterator.prototype._seek = function (target) { if (target.length === 0) { - throw new Error('cannot seek() to an empty key') + throw new Error('cannot seek() to an empty target') } this.cache = null diff --git a/test/iterator-test.js b/test/iterator-test.js index 6e611ee8..e0399262 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -3,21 +3,21 @@ const iota = require('iota-array') const lexi = require('lexicographic-integer') const util = require('util') -make('iterator throws if key is not a string or buffer', function (db, t, done) { - var keys = [null, undefined, 1, true, false] - var pending = keys.length +make('iterator#seek throws if target is empty', function (db, t, done) { + var targets = [null, undefined, '', Buffer.alloc(0), []] + var pending = targets.length - keys.forEach(function (key) { - var error + targets.forEach(function (target) { var ite = db.iterator() + var error try { - ite.seek(key) - } catch (e) { - error = e + ite.seek(target) + } catch (err) { + error = err.message } - t.ok(error, 'had error from seek()') + t.is(error, 'cannot seek() to an empty target', 'got error') ite.end(end) }) @@ -86,8 +86,8 @@ make('reverse seek from invalid range', function (db, t, done) { ite.seek('zzz') ite.next(function (err, key, value) { t.error(err, 'no error') - t.same(key.toString(), 'two', 'end of iterator') - t.same(value.toString(), '2', 'end of iterator') + t.same(key.toString(), 'two') + t.same(value.toString(), '2') ite.end(done) }) }) @@ -132,17 +132,20 @@ make('iterator optimized for seek', function (db, t, done) { make('iterator seek before next has completed', function (db, t, done) { var ite = db.iterator() + var error + ite.next(function (err, key, value) { t.error(err, 'no error from next()') ite.end(done) }) - var error + try { ite.seek('two') - } catch (e) { - error = e + } catch (err) { + error = err.message } - t.ok(error, 'had error from seek() before next() has completed') + + t.is(error, 'cannot call seek() before next() has completed', 'got error') }) make('close db with open iterator', function (db, t, done) { @@ -170,12 +173,14 @@ make('iterator seek after end', function (db, t, done) { ite.end(function (err) { t.error(err, 'no error from end()') var error + try { ite.seek('two') - } catch (e) { - error = e + } catch (err) { + error = err.message } - t.ok(error, 'had error from seek() after end()') + + t.is(error, 'cannot call seek() after end()', 'got error') done() }) }) From 1e363aab8b04835a90b562e6221accf590ea2186 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sun, 15 Jul 2018 15:59:51 +0200 Subject: [PATCH 08/13] implement _serializeKey and _serializeValue With undefined behavior for nullish targets (range options and seek targets). Previously, nullish range options were ignored and seek(null) and seek(undefined) would throw an error. Now they translate to String(null) and String(undefined). This change makes it explicit that leveldown only supports buffers and strings. Nullish targets do have a meaning in the ecosystem; that meaning should be given at a higher level like encoding-down. In other words, it isn't leveldown's concern anymore. --- leveldown.js | 8 ++++++++ test/iterator-test.js | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/leveldown.js b/leveldown.js index 91353932..43c82dcf 100644 --- a/leveldown.js +++ b/leveldown.js @@ -29,6 +29,14 @@ LevelDOWN.prototype._close = function (callback) { this.binding.close(callback) } +LevelDOWN.prototype._serializeKey = function (key) { + return Buffer.isBuffer(key) ? key : String(key) +} + +LevelDOWN.prototype._serializeValue = function (value) { + return Buffer.isBuffer(value) ? value : String(value) +} + LevelDOWN.prototype._put = function (key, value, options, callback) { this.binding.put(key, value, options, callback) } diff --git a/test/iterator-test.js b/test/iterator-test.js index e0399262..60fee8f2 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -4,7 +4,7 @@ const lexi = require('lexicographic-integer') const util = require('util') make('iterator#seek throws if target is empty', function (db, t, done) { - var targets = [null, undefined, '', Buffer.alloc(0), []] + var targets = ['', Buffer.alloc(0), []] var pending = targets.length targets.forEach(function (target) { From 23222b587d09bcfd31be9d058af6919e50482f2e Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Fri, 19 Oct 2018 11:06:30 +0200 Subject: [PATCH 09/13] moved seek tests to abstract-leveldown --- test/iterator-test.js | 208 +----------------------------------------- 1 file changed, 4 insertions(+), 204 deletions(-) diff --git a/test/iterator-test.js b/test/iterator-test.js index 60fee8f2..3203eacd 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -1,8 +1,9 @@ const make = require('./make') -const iota = require('iota-array') -const lexi = require('lexicographic-integer') -const util = require('util') +// const iota = require('iota-array') // TODO: remove if unused +// const lexi = require('lexicographic-integer') // TODO: remove if unused +// This test isn't included in abstract-leveldown because +// the empty-check is currently performed by leveldown. make('iterator#seek throws if target is empty', function (db, t, done) { var targets = ['', Buffer.alloc(0), []] var pending = targets.length @@ -27,71 +28,6 @@ make('iterator#seek throws if target is empty', function (db, t, done) { } }) -make('iterator is seekable', function (db, t, done) { - var ite = db.iterator() - ite.seek('two') - ite.next(function (err, key, value) { - t.error(err, 'no error') - t.same(key.toString(), 'two', 'key matches') - t.same(value.toString(), '2', 'value matches') - ite.next(function (err, key, value) { - t.error(err, 'no error') - t.same(key, undefined, 'end of iterator') - t.same(value, undefined, 'end of iterator') - ite.end(done) - }) - }) -}) - -make('iterator is seekable with buffer', function (db, t, done) { - var ite = db.iterator() - ite.seek(Buffer.from('two')) - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - t.equal(key.toString(), 'two', 'key matches') - t.equal(value.toString(), '2', 'value matches') - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - t.equal(key, undefined, 'end of iterator') - t.equal(value, undefined, 'end of iterator') - ite.end(done) - }) - }) -}) - -make('reverse seek in the middle', function (db, t, done) { - var ite = db.iterator({ reverse: true, limit: 1 }) - ite.seek('three!') - ite.next(function (err, key, value) { - t.error(err, 'no error') - t.same(key.toString(), 'three', 'key matches') - t.same(value.toString(), '3', 'value matches') - ite.end(done) - }) -}) - -make('iterator invalid seek', function (db, t, done) { - var ite = db.iterator() - ite.seek('zzz') - ite.next(function (err, key, value) { - t.error(err, 'no error') - t.same(key, undefined, 'end of iterator') - t.same(value, undefined, 'end of iterator') - ite.end(done) - }) -}) - -make('reverse seek from invalid range', function (db, t, done) { - var ite = db.iterator({ reverse: true }) - ite.seek('zzz') - ite.next(function (err, key, value) { - t.error(err, 'no error') - t.same(key.toString(), 'two') - t.same(value.toString(), '2') - ite.end(done) - }) -}) - make('iterator optimized for seek', function (db, t, done) { var batch = db.batch() batch.put('a', 1) @@ -130,24 +66,6 @@ make('iterator optimized for seek', function (db, t, done) { }) }) -make('iterator seek before next has completed', function (db, t, done) { - var ite = db.iterator() - var error - - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - ite.end(done) - }) - - try { - ite.seek('two') - } catch (err) { - error = err.message - } - - t.is(error, 'cannot call seek() before next() has completed', 'got error') -}) - make('close db with open iterator', function (db, t, done) { var ite = db.iterator() var cnt = 0 @@ -165,121 +83,3 @@ make('close db with open iterator', function (db, t, done) { done(false) }) }) - -make('iterator seek after end', function (db, t, done) { - var ite = db.iterator() - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - ite.end(function (err) { - t.error(err, 'no error from end()') - var error - - try { - ite.seek('two') - } catch (err) { - error = err.message - } - - t.is(error, 'cannot call seek() after end()', 'got error') - done() - }) - }) -}) - -make('iterator seek respects range', function (db, t, done) { - db.batch(pairs(10), function (err) { - t.error(err, 'no error from batch()') - - var pending = 0 - - expect({ gt: '5' }, '4', undefined) - expect({ gt: '5' }, '5', undefined) - expect({ gt: '5' }, '6', '6') - - expect({ gte: '5' }, '4', undefined) - 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) - - expect({ lte: '5' }, '4', '4') - 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) - - expect({ lte: '5', reverse: true }, '4', '4') - 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') - - expect({ gte: '5', reverse: true }, '4', undefined) - 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) - expect({ gt: '7', lte: '8' }, '8', '8') - - function expect (range, target, expected) { - pending++ - var ite = db.iterator(range) - - ite.seek(target) - ite.next(function (err, key, value) { - t.error(err, 'no error from next()') - - var tpl = 'seek(%s) on %s yields %s' - var msg = util.format(tpl, target, util.inspect(range), expected) - - if (expected === undefined) { - t.equal(value, undefined, msg) - } else { - t.equal(value.toString(), expected, msg) - } - - ite.end(function (err) { - t.error(err, 'no error from end()') - if (!--pending) done() - }) - }) - } - }) -}) - -function pairs (length, opts) { - opts = opts || {} - return iota(length).filter(not(opts.not)).map(function (k) { - var key = opts.lex ? lexi.pack(k, 'hex') : '' + k - return { type: 'put', key: key, value: '' + k } - }) -} - -function not (n) { - if (typeof n === 'function') return function (k) { return !n(k) } - return function (k) { return k !== n } -} From 87e83cc14d06aa4bf4aa9f1eea99d9ee22b832a4 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Fri, 19 Oct 2018 11:08:25 +0200 Subject: [PATCH 10/13] remove unused iota-array and lexicographic-integer devDependencies --- package.json | 2 -- test/iterator-test.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/package.json b/package.json index 67f5d935..4313ff5f 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,7 @@ "coveralls": "^3.0.2", "delayed": "~1.0.1", "du": "~0.1.0", - "iota-array": "~1.0.0", "level-concat-iterator": "^2.0.0", - "lexicographic-integer": "~1.1.0", "mkfiletree": "~1.0.1", "monotonic-timestamp": "~0.0.8", "nyc": "^12.0.2", diff --git a/test/iterator-test.js b/test/iterator-test.js index 3203eacd..22647b3b 100644 --- a/test/iterator-test.js +++ b/test/iterator-test.js @@ -1,6 +1,4 @@ const make = require('./make') -// const iota = require('iota-array') // TODO: remove if unused -// const lexi = require('lexicographic-integer') // TODO: remove if unused // This test isn't included in abstract-leveldown because // the empty-check is currently performed by leveldown. From 1fb0e4f980372e6a86da75a80d65ab66044f735a Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Fri, 19 Oct 2018 12:34:20 +0200 Subject: [PATCH 11/13] target Level/abstract-leveldown#b610da0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4313ff5f..4d5d2b7f 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "github:Level/abstract-leveldown#0f42686", + "abstract-leveldown": "github:Level/abstract-leveldown#b610da0", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", From 9631b996d9f73045822a9936bd5323525d2dced9 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sat, 20 Oct 2018 15:05:03 +0200 Subject: [PATCH 12/13] target abstract-leveldown@6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d5d2b7f..6a7bf9a2 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ ], "main": "leveldown.js", "dependencies": { - "abstract-leveldown": "github:Level/abstract-leveldown#b610da0", + "abstract-leveldown": "~6.0.0", "bindings": "~1.3.0", "fast-future": "~1.0.2", "nan": "~2.11.0", From 1e1b1de2cbaffd33f7f369e966a1669acea500d9 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Sat, 20 Oct 2018 15:11:29 +0200 Subject: [PATCH 13/13] readme: value may not be null or undefined --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07cfdd2d..3c5da2e0 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ The following options are for advanced performance tuning. Modify them only if y ### `db.put(key, value[, options], callback)` put() is an instance method on an existing database object, used to store new entries, or overwrite existing entries in the LevelDB store. -The `key` and `value` objects may either be strings or Buffers. Other object types are converted to strings with the `toString()` method. Keys may not be `null` or `undefined` and objects converted with `toString()` should not result in an empty-string. Values of `null`, `undefined`, `''`, `[]` and `Buffer.alloc(0)` (and any object resulting in a `toString()` of one of these) will be stored as a zero-length character array and will therefore be retrieved as either `''` or `Buffer.alloc(0)` depending on the type requested. +The `key` and `value` objects may either be strings or Buffers. Other object types are converted to strings with the `toString()` method. Keys may not be `null` or `undefined` and objects converted with `toString()` should not result in an empty-string. Values may not be `null` or `undefined`. Values of `''`, `[]` and `Buffer.alloc(0)` (and any object resulting in a `toString()` of one of these) will be stored as a zero-length character array and will therefore be retrieved as either `''` or `Buffer.alloc(0)` depending on the type requested. A richer set of data-types is catered for in `levelup`.