pax_global_header 0000666 0000000 0000000 00000000064 13553424167 0014524 g ustar 00root root 0000000 0000000 52 comment=ba4540a3cd530365dccf258cf94eb73ce96f4f3c
abstract-leveldown-6.2.2/ 0000775 0000000 0000000 00000000000 13553424167 0015333 5 ustar 00root root 0000000 0000000 abstract-leveldown-6.2.2/.airtap.yml 0000664 0000000 0000000 00000000452 13553424167 0017415 0 ustar 00root root 0000000 0000000 browsers:
- name: chrome
version: latest
platform: Windows 10
- name: internet explorer
version: '11'
- name: firefox
version: latest
platform: Windows 10
- name: iphone
version: '9.0'
- name: android
version: '6.0'
- name: microsoftedge
version: latest
abstract-leveldown-6.2.2/.gitignore 0000664 0000000 0000000 00000000042 13553424167 0017317 0 ustar 00root root 0000000 0000000 node_modules
coverage
.nyc_output
abstract-leveldown-6.2.2/.travis.yml 0000664 0000000 0000000 00000000655 13553424167 0017452 0 ustar 00root root 0000000 0000000 sudo: false
language: node_js
matrix:
fast_finish: true
include:
- node_js: 6
env: CMD=test
- node_js: 8
env: CMD=test
- node_js: 10
env: CMD=test
- node_js: stable
env: CMD=test-browsers
addons:
sauce_connect: true
hosts:
- airtap.local
before_script: git fetch --tags
script:
- DEBUG=airtap:* npm run $CMD
after_success: npm run coverage
notifications:
email: false
abstract-leveldown-6.2.2/CHANGELOG.md 0000664 0000000 0000000 00000120305 13553424167 0017145 0 ustar 00root root 0000000 0000000 # Changelog
_**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md)._
## [6.2.2] - 2019-10-21
### Added
- Add more range tests ([#353](https://github.com/Level/abstract-leveldown/issues/353)) ([**@vweevers**](https://github.com/vweevers))
## [6.2.1] - 2019-10-01
### Fixed
- Fix `manifest-test` to open & close its db ([#352](https://github.com/Level/abstract-leveldown/issues/352)) ([**@vweevers**](https://github.com/vweevers))
## [6.2.0] - 2019-09-30
### Changed
- Upgrade `hallmark` devDependency from `^1.0.0` to `^2.0.0` ([#349](https://github.com/Level/abstract-leveldown/issues/349)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `standard` devDependency from `^13.0.1` to `^14.0.0` ([#348](https://github.com/Level/abstract-leveldown/issues/348)) ([**@vweevers**](https://github.com/vweevers))
### Added
- Add manifest ([Level/community#83](https://github.com/Level/community/issues/83)) ([#351](https://github.com/Level/abstract-leveldown/issues/351)) ([**@vweevers**](https://github.com/vweevers))
- Document mandatory methods ([#350](https://github.com/Level/abstract-leveldown/issues/350)) ([**@vweevers**](https://github.com/vweevers))
## [6.1.1] - 2019-08-18
### Fixed
- Remove `process.emitWarning` because it breaks AppVeyor builds ([`8e963c3`](https://github.com/Level/abstract-leveldown/commit/8e963c3)) ([**@vweevers**](https://github.com/vweevers))
## [6.1.0] - 2019-08-18
### Changed
- Upgrade `hallmark` devDependency from `^0.1.0` to `^1.0.0` ([#343](https://github.com/Level/abstract-leveldown/issues/343)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `standard` devDependency from `^12.0.0` to `^13.0.1` ([#341](https://github.com/Level/abstract-leveldown/issues/341)) ([**@vweevers**](https://github.com/vweevers))
### Added
- Add `clear()` method to delete all entries or a range ([#310](https://github.com/Level/abstract-leveldown/issues/310)) ([**@vweevers**](https://github.com/vweevers)).
**Historical Note** The `clear()` method is experimental and optional for the time being. Please see the [README](https://github.com/Level/abstract-leveldown) for details.
## [6.0.3] - 2019-04-26
### Changed
- Upgrade `nyc` devDependency from `^13.2.0` to `^14.0.0` ([#334](https://github.com/Level/abstract-leveldown/issues/334)) ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Fix and test asynchronicity of empty batch ([#337](https://github.com/Level/abstract-leveldown/issues/337)) ([**@vweevers**](https://github.com/vweevers))
- Fix Level badge ([`8993257`](https://github.com/Level/abstract-leveldown/commit/8993257)) ([**@vweevers**](https://github.com/vweevers))
- Remove link to dead website ([`c0abe28`](https://github.com/Level/abstract-leveldown/commit/c0abe28)) ([**@vweevers**](https://github.com/vweevers))
## [6.0.2] - 2019-03-30
### Changed
- Upgrade `sinon` devDependency from `^6.0.0` to `^7.2.4` ([#330](https://github.com/Level/abstract-leveldown/issues/330)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Upgrade `nyc` devDependency from `^12.0.2` to `^13.2.0` ([#327](https://github.com/Level/abstract-leveldown/issues/327)) ([**@vweevers**](https://github.com/vweevers))
- Upgrade `airtap` devDependency from `0.1.0` to `^2.0.0` ([#323](https://github.com/Level/abstract-leveldown/issues/323)) ([**@vweevers**](https://github.com/vweevers))
- Apply common project tweaks ([#324](https://github.com/Level/abstract-leveldown/issues/324), [#325](https://github.com/Level/abstract-leveldown/issues/325)) ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Fix subtests by adding `t.plan()` ([#329](https://github.com/Level/abstract-leveldown/issues/329)) ([**@vweevers**](https://github.com/vweevers))
## [6.0.1] - 2018-12-27
### Changed
- Upgrade `hallmark` devDependency from `0.0.2` to `0.1.0` ([#316](https://github.com/level/abstract-leveldown/issues/316)) ([**@vweevers**](https://github.com/vweevers))
- Split v6 upgrade guide into sections for consumers and implementors ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Remove range tests that assumed zero-length strings or Buffers meant "not defined" ([#319](https://github.com/level/abstract-leveldown/issues/319)) ([**@vweevers**](https://github.com/vweevers))
## [6.0.0] - 2018-10-20
_If you are upgrading, please consult the [Upgrade Guide](UPGRADING.md#v6)._
### Changed
- Upgrade `airtap` devDependency from `0.0.5` to `0.1.0` ([#229](https://github.com/level/abstract-leveldown/issues/229), [#231](https://github.com/level/abstract-leveldown/issues/231), [#245](https://github.com/level/abstract-leveldown/issues/245), [`029f56a`](https://github.com/level/abstract-leveldown/commit/029f56a), [#252](https://github.com/level/abstract-leveldown/issues/252)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Upgrade `sinon` devDependency from `^5.0.0` to `^6.0.0` ([#232](https://github.com/level/abstract-leveldown/issues/232)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Upgrade `standard` devDependency from `^11.0.0` to `^12.0.0` ([#303](https://github.com/level/abstract-leveldown/issues/303)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Reject nullish values ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Make default `_serializeKey` and `_serializeValue` identity functions ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Don't coerce keys to strings to check if they're empty, instead check arrays explicitly ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Make `db` property mandatory and public on iterator and chained batch ([#257](https://github.com/level/abstract-leveldown/issues/257), [#309](https://github.com/level/abstract-leveldown/issues/309)) ([**@vweevers**](https://github.com/vweevers))
- Align `AbstractChainedBatch#_clear` with `_put` and `_del` ([#257](https://github.com/level/abstract-leveldown/issues/257)) ([**@vweevers**](https://github.com/vweevers))
- Add `AbstractChainedBatch#_write` with options ([#257](https://github.com/level/abstract-leveldown/issues/257)) ([**@vweevers**](https://github.com/vweevers))
- Use `level-concat-iterator` instead of `collectEntries` ([#246](https://github.com/level/abstract-leveldown/issues/246)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Document API and test suite ([#251](https://github.com/level/abstract-leveldown/issues/251), [#290](https://github.com/level/abstract-leveldown/issues/290), [#295](https://github.com/level/abstract-leveldown/issues/295), [#296](https://github.com/level/abstract-leveldown/issues/296), [#305](https://github.com/level/abstract-leveldown/issues/305)) ([**@vweevers**](https://github.com/vweevers))
- Export test suite as a single function ([#271](https://github.com/level/abstract-leveldown/issues/271), [#293](https://github.com/level/abstract-leveldown/issues/293), [#297](https://github.com/level/abstract-leveldown/issues/297)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Use factory function to create `db` instances in test suite ([#258](https://github.com/level/abstract-leveldown/issues/258), [#268](https://github.com/level/abstract-leveldown/issues/268), [#282](https://github.com/level/abstract-leveldown/issues/282)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Isolate snapshot tests so that they can be skipped ([#239](https://github.com/level/abstract-leveldown/issues/239), [#274](https://github.com/level/abstract-leveldown/issues/274)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Isolate openAdvanced tests so that they can be skipped ([#271](https://github.com/level/abstract-leveldown/issues/271)) ([**@vweevers**](https://github.com/vweevers))
- Rename `abstract/` to `test/` ([#253](https://github.com/level/abstract-leveldown/issues/253)) ([**@vweevers**](https://github.com/vweevers))
- Refactor internal test methods to have the same signature `(test, testCommon)` ([#268](https://github.com/level/abstract-leveldown/issues/268), [#275](https://github.com/level/abstract-leveldown/issues/275)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Prefer `exports.*` over `module.exports.*` ([#276](https://github.com/level/abstract-leveldown/issues/276)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Tweak copyright years for less maintenance ([`0b2949a`](https://github.com/level/abstract-leveldown/commit/0b2949a)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Add `iterator#seek()` ([#237](https://github.com/level/abstract-leveldown/issues/237), [#302](https://github.com/level/abstract-leveldown/issues/302), [#307](https://github.com/level/abstract-leveldown/issues/307)) ([**@vweevers**](https://github.com/vweevers), [**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `nyc` and `coveralls` devDependencies for code coverage ([#253](https://github.com/level/abstract-leveldown/issues/253)) ([**@vweevers**](https://github.com/vweevers))
- Add `setUp` and `tearDown` to all sub tests ([#279](https://github.com/level/abstract-leveldown/issues/279), [#289](https://github.com/level/abstract-leveldown/issues/289)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add test for implementations that cannot support snapshots ([#239](https://github.com/level/abstract-leveldown/issues/239)) ([**@vweevers**](https://github.com/vweevers))
- Add `hallmark` devDependency for Markdown style and contributors ([#312](https://github.com/level/abstract-leveldown/issues/312)) ([**@vweevers**](https://github.com/vweevers))
### Removed
- Remove `location` ([#258](https://github.com/level/abstract-leveldown/issues/258)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `lastLocation`, `cleanup`, `rimraf` ([#249](https://github.com/level/abstract-leveldown/issues/249)) ([**@vweevers**](https://github.com/vweevers))
- Remove IE10 from Sauce Labs test matrix ([#312](https://github.com/level/abstract-leveldown/issues/312)) ([**@vweevers**](https://github.com/vweevers))
- Remove node 9 from Travis ([`0b52395`](https://github.com/level/abstract-leveldown/commit/0b52395)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove tests that assumed support of boolean and NaN keys ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Remove range tests that assumed `null` meant "not defined" ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Remove sync test from `test/put-test.js` ([#300](https://github.com/level/abstract-leveldown/issues/300)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove empty `errorValues()` test ([#273](https://github.com/level/abstract-leveldown/issues/273)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove default `testCommon` parameter ([#264](https://github.com/level/abstract-leveldown/issues/264), [#271](https://github.com/level/abstract-leveldown/issues/271)) ([**@vweevers**](https://github.com/vweevers))
- Remove `contributors` from `package.json` ([`542f350`](https://github.com/level/abstract-leveldown/commit/542f350)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove copyright headers from code ([`a36c04f`](https://github.com/level/abstract-leveldown/commit/a36c04f)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Make sure all `t.throw` tests check error messages correctly ([#286](https://github.com/level/abstract-leveldown/issues/286)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Check options objects properly for `null` ([#257](https://github.com/level/abstract-leveldown/issues/257), [#288](https://github.com/level/abstract-leveldown/issues/288)) ([**@ralphtheninja**](https://github.com/ralphtheninja), [**@vweevers**](https://github.com/vweevers))
- Serialize range options same as keys ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
- Allow nullish and empty range options ([#277](https://github.com/level/abstract-leveldown/issues/277)) ([**@vweevers**](https://github.com/vweevers))
## [5.0.0] - 2018-05-22
### Changed
- Upgrade `sinon` to `^5.0.0` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Tweak README ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Replace `const` with `var` to support IE10 ([**@vweevers**](https://github.com/vweevers))
### Added
- Add node 10 to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `airtap` for browser tests ([**@vweevers**](https://github.com/vweevers))
### Removed
- Remove node 4, 5 and 7 from Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove TypeScript tests ([**@vweevers**](https://github.com/vweevers))
- Remove TypeScript typings ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [4.0.3] - 2018-02-21
### Changed
- Upgrade `ts-node` to `^5.0.0` ([**@zixia**](https://github.com/zixia))
- Upgrade `standard` to `^11.0.0` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Remove invalid TypeScript from `Batch` ([**@Tapppi**](https://github.com/Tapppi))
- Add JSDoc to incorrectly inferred TypeScript types ([**@Tapppi**](https://github.com/Tapppi))
## [4.0.2] - 2018-02-09
### Fixed
- Fix `iterator#next` to return `this` ([**@vweevers**](https://github.com/vweevers))
## [4.0.1] - 2018-02-09
### Added
- Run test suite in TypeScript in addition to Node.js ([**@vweevers**](https://github.com/vweevers))
- Add TypeScript smoke test ([**@vweevers**](https://github.com/vweevers))
- Add TypeScript readme section with stability badge ([**@vweevers**](https://github.com/vweevers))
### Removed
- Remove obsolete parameters from tests ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Update TypeScript typings for v4 ([**@vweevers**](https://github.com/vweevers))
- Use ES6 classes in tests to please TypeScript ([**@vweevers**](https://github.com/vweevers))
- Define default methods on prototype to please TypeScript ([**@vweevers**](https://github.com/vweevers))
**Historical Note** This was released as a patch because it only changed tests
and TypeScript typings (which are marked experimental and don't follow semver).
## [4.0.0] - 2018-01-20
### Changed
- Ignore empty range options in `AbstractLevelDOWN#_setupIteratorOptions` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Make `testCommon.js` the default value for `testCommon` parameter ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Use `Buffer.isBuffer()` instead of `AbstractLevelDOWN#isBuffer` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Cleanup iterator tests ([#161](https://github.com/level/abstract-leveldown/issues/161)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Pass test function as a parameter instead of setting local global ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Assert batch type is `'put'` or `'del'` ([**@vweevers**](https://github.com/vweevers))
- Assert batch array elements are objects ([**@vweevers**](https://github.com/vweevers))
### Added
- Add `standard` for linting ([#150](https://github.com/level/abstract-leveldown/issues/150)) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Test that callbacks are called asynchronously ([**@vweevers**](https://github.com/vweevers))
- Test serialization extensibility ([**@vweevers**](https://github.com/vweevers))
- Add [**@vweevers**](https://github.com/vweevers) to contributors ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add upgrade guide in `UPGRADING.md` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add node 9 to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Removed
- Remove `isLevelDOWN` function and corresponding tests ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `AbstractLevelDOWN#approximateSize` method and corresponding tests ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove `testBuffer` in `abstract/put-get-del-test.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Remove object value test in `abstract/put-test.js` ([**@vweevers**](https://github.com/vweevers))
- Remove serialize buffer tests ([**@vweevers**](https://github.com/vweevers))
- Remove serialize object tests ([**@vweevers**](https://github.com/vweevers))
- Remove `BufferType` parameter in `abstract/put-get-del-test.js`, use `Buffer` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Ensure stores are closed properly (fixes problems on Windows) ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Call back errors on next tick to avoid `zalgo` ([**@vweevers**](https://github.com/vweevers))
## [3.0.0] - 2017-11-04
### Added
- Add node version badge ([**@vweevers**](https://github.com/vweevers))
### Removed
- Drop support for `0.12`. Cause for new major version! ([**@vweevers**](https://github.com/vweevers))
### Fixed
- Fix errors in `index.d.ts` ([**@sandersn**](https://github.com/sandersn))
## [2.7.2] - 2017-10-11
### Changed
- Update `README` with new style ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.7.1] - 2017-09-30
### Changed
- Refactor typings as ES2015 module ([**@MeirionHughes**](https://github.com/MeirionHughes))
## [2.7.0] - 2017-09-12
### Added
- Add `TypeScript` definitions in `index.d.ts` ([**@MeirionHughes**](https://github.com/MeirionHughes))
## [2.6.3] - 2017-09-05
### Changed
- Upgrade dependencies ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Convert nullish values to empty strings ([**@bigeasy**](https://github.com/bigeasy))
- Use `t.equal(a, b)` instead of `t.ok(a === b)` ([**@bigeasy**](https://github.com/bigeasy))
- Relax tests for serializing object in `abstract/chained-batch-test.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Add `GreenKeeper` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Test key/value serialization ([**@bigeasy**](https://github.com/bigeasy))
- Test `undefined` value serializing to empty string ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Document `.status` property ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.6.2] - 2017-07-30
### Changed
- Upgrade dependencies and float `devDependencies` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Update copyright years ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Update node versions on Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Test serialization extensibility ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
- Fix put test on object serialization ([**@juliangruber**](https://github.com/juliangruber))
## [2.6.1] - 2016-09-12
### Fixed
- Fix `null` case in default value serializer (fixes problems in `2.6.0`) ([**@juliangruber**](https://github.com/juliangruber))
## [2.6.0] - 2016-03-10
### Changed
- Use proto delegation to patch methods on db ([**@deanlandolt**](https://github.com/deanlandolt))
- Allow serialization functions to return buffers ([**@deanlandolt**](https://github.com/deanlandolt))
### Added
- Add `collectBatchOps` function to buffer `_put` and `_del` inputs in `abstract/chained-batch-test.js` ([**@deanlandolt**](https://github.com/deanlandolt))
### Removed
- Remove unnecessary initialization hackery in `abstract/chained-batch-test.js` ([**@deanlandolt**](https://github.com/deanlandolt))
**Historical Note** This release was a breaking change. See [**@juliangruber**](https://github.com/juliangruber)'s [comment](https://github.com/Level/abstract-leveldown/pull/85#issuecomment-246980978) for more information.
## [2.5.0] - 2016-05-01
### Changed
- Upgrade dependencies and add more node versions to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Add dependency badge to `README` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `AbstractLevelDOWN#_serializeKey` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractLevelDOWN#_serializeValue` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractChainedBatch#_serializeKey` ([**@juliangruber**](https://github.com/juliangruber))
- Add `AbstractChainedBatch#_serializeValue` ([**@juliangruber**](https://github.com/juliangruber))
- Test `_serialize` with object and buffer ([**@juliangruber**](https://github.com/juliangruber))
### Removed
- Remove stringification of keys and values ([**@juliangruber**](https://github.com/juliangruber))
- Remove `.toBuffer` ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
- Update `memdown` url ([**@ralphtheninja**](https://github.com/ralphtheninja))
- `AbstractLevelDOWN#._checkKey` does not take three parameters ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Only show build status for the master branch ([**@watson**](https://github.com/watson))
- Fix minor typos in `README` ([**@timkuijsten**](https://github.com/timkuijsten))
## [2.4.1] - 2015-08-29
### Fixed
- Remove use of `const` ([**@nolanlawson**](https://github.com/nolanlawson))
## [2.4.0] - 2015-05-19
### Added
- Add `.status` property to `AbstractLevelDOWN` ([**@juliangruber**](https://github.com/juliangruber))
## [2.3.1] - 2015-05-18
### Added
- Link to `level/community` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Removed
- Extract `Contributors` section from `README` into `level/community` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Document `isLevelDown` function ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.3.0] - 2015-05-18
### Changed
- Use `t.equal(a, b)` instead of `t.ok(a === b)` ([**@juliangruber**](https://github.com/juliangruber))
- Export API from `index.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Import `isLevelDOWN` function to `is-leveldown.js` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.2.2] - 2015-05-13
### Fixed
- Revert changes to `location` in `2.2.1` ([**@juliangruber**](https://github.com/juliangruber))
## [2.2.1] - 2015-05-12
### Fixed
- Copy paste error gave wrong test description ([**@ralphtheninja**](https://github.com/ralphtheninja))
- `t.throws()` is different for `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Assert `location` is not an empty string ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.2.0] - 2015-05-10
### Added
- Test `{ sync: true }` option in `abstract/put-test.js` ([**@juliangruber**](https://github.com/juliangruber))
## [2.1.4] - 2015-04-28
### Fixed
- Use `t.equal()` with `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.3] - 2015-04-28
### Changed
- Change from `tap` to `tape` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.2] - 2015-04-27
### Changed
- Convert buffer to string so we can compare ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.1] - 2015-04-27
### Changed
- Update logo and copyright ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Added
- Add [**@ralphtheninja**](https://github.com/ralphtheninja) to contributors ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Add `0.12` and `iojs` to Travis ([**@ralphtheninja**](https://github.com/ralphtheninja))
### Fixed
- Include `.nonErrorValues()` test in `abstract/put-get-del-test.js` ([**@hden**](https://github.com/hden))
- `rvagg/node-abstract-leveldown` moved to `level/abstract-leveldown` ([**@ralphtheninja**](https://github.com/ralphtheninja))
- Fix Travis for `0.8` ([**@ralphtheninja**](https://github.com/ralphtheninja))
## [2.1.0] - 2014-11-09
### Changed
- Use `setTimeout` instead of `process.nextTick` ([**@bigeasy**](https://github.com/bigeasy))
### Added
- Add [**@watson**](https://github.com/watson) to contributors ([**@rvagg**](https://github.com/rvagg))
### Fixed
- Don't fail if no value is returned by `._get` ([**@watson**](https://github.com/watson))
- Use `error` test function when testing for errors ([**@watson**](https://github.com/watson))
## [2.0.3] - 2014-10-02
No change.
## [2.0.2] - 2014-10-02
### Added
- Test atomic batch operations ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
## [2.0.1] - 2014-09-01
### Changed
- Set default values for options to `.open`, `.get`, `.put`, `.del` and `.batch` ([**@watson**](https://github.com/watson))
- Update pattern for setting default options for the iterator ([**@watson**](https://github.com/watson))
- Allow boolean options to be falsy/truthy ([**@watson**](https://github.com/watson))
### Removed
- Remove default options that are too `LevelDOWN` specific ([**@watson**](https://github.com/watson))
## [2.0.0] - 2014-08-26
### Changed
- Switch to allowing writes of empty values, `null`, `undefined`, `''`, `[]` and empty buffer ([**@juliangruber**](https://github.com/juliangruber))
- Rename `AbstractLevelDOWN#_checkKeyValue` to `AbstractLevelDOWN#_checkKey` ([**@rvagg**](https://github.com/rvagg))
## [1.0.0] - 2014-08-24
### Changed
- Ensure `Boolean` iterator options are `Boolean` ([**@watson**](https://github.com/watson))
### Added
- Test that an error is thrown when location isn't a string ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Test opening and closing the store ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Test iterator with `limit` set to `0` ([**@watson**](https://github.com/watson))
- Add more tests to `abstract/batch-test.js` ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
- Set default values of iterator options ([**@watson**](https://github.com/watson))
- Account for batch options that are `null` ([**@calvinmetcalf**](https://github.com/calvinmetcalf))
### Removed
- Remove options.start hackery ([**@rvagg**](https://github.com/rvagg))
## [0.12.4] - 2014-08-20
### Changed
- Change license to plain MIT ([**@andrewrk**](https://github.com/andrewrk))
### Added
- Test that `simple-iterator` returns buffers ([**@kesla**](https://github.com/kesla))
- Test implicit snapshots ([**@kesla**](https://github.com/kesla))
## [0.12.3] - 2014-06-27
### Changed
- Upgrade `xtend` dependency ([**@andrewrk**](https://github.com/andrewrk))
## [0.12.2] - 2014-04-26
### Changed
- Have `isTypedArray` check for existence of `ArrayBuffer` and `Uint8Array` constructors before usage ([**@rvagg**](https://github.com/rvagg))
## [0.12.1] - 2014-04-26
### Changed
- Set default `BufferType` in `abstract/put-get-del-test.js` to `Buffer` instead of `ArrayBuffer` ([**@maxogden**](https://github.com/maxogden))
## [0.12.0] - 2014-03-12
### Changed
- Revert to pure `Buffer` and remove usage of `Uint16Array` ([**@rvagg**](https://github.com/rvagg))
## [0.11.4] - 2014-03-11
### Removed
- Remove duplicate call to `t.end()` ([**@maxogden**](https://github.com/maxogden))
## [0.11.3] - 2014-01-26
### Changed
- Loosen the buffer type check ([**@rvagg**](https://github.com/rvagg))
## [0.11.2] - 2013-12-05
### Added
- Add npm badges ([**@rvagg**](https://github.com/rvagg))
### Fixed
- Fix iterator tests in `test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.11.1] - 2013-11-15
### Changed
- Adjust `abstract/approximate-size-test.js` to account for snappy compression ([**@rvagg**](https://github.com/rvagg))
## [0.11.0] - 2013-10-14
### Added
- Normalize `iterator()` options with `AbstractLevelDOWN#_setupIteratorOptions` ([**@rvagg**](https://github.com/rvagg))
## [0.10.2] - 2013-09-06
### Changed
- Refactor duplicated versions of `isTypedArray` into `abstract/util.js` ([**@rvagg**](https://github.com/rvagg))
- Refactor duplicated versions of `'NotFound'` checks into `abstract/util.js`, fixed too-strict version in `get-test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.10.1] - 2013-08-29
### Changed
- Relax check for `Not Found` error message to be case insensitive in `get-test.js` ([**@rvagg**](https://github.com/rvagg))
### Added
- Add [**@substack**](https://github.com/substack) to contributors ([**@rvagg**](https://github.com/rvagg))
## [0.10.0] - 2013-08-19
### Added
- Test `gt`, `gte`, `lt` and `lte` ranges ([**@dominictarr**](https://github.com/dominictarr))
## [0.9.0] - 2013-08-11
### Changed
- Make `AbstractChainedBatch` extensible ([**@kesla**](https://github.com/kesla))
- Export `AbstractChainedBatch` from `abstract-leveldown.js` ([**@kesla**](https://github.com/kesla))
### Added
- Test simultaneous get's ([**@kesla**](https://github.com/kesla))
- Test `AbstractChainedBatch` extensibility ([**@kesla**](https://github.com/kesla))
### Fixed
- Fix broken test assertion in `abstract/get-test.js` ([**@rvagg**](https://github.com/rvagg))
- Fix tests that weren't running properly ([**@kesla**](https://github.com/kesla))
## [0.8.2] - 2013-08-02
No changes. Merely published changes made in `0.8.1`.
## [0.8.1] - 2013-08-02
### Changed
- Remove use of `const` in `testCommon.js` ([**@rvagg**](https://github.com/rvagg))
**Historical Note** The version in `package.json` was changed from `0.7.4` to `0.8.1`. The `0.8.1` tag exists but this version was never published to npm.
## [0.8.0] - 2013-08-02
### Changed
- Use `process.browser` check instead of `process.title == 'browser'` ([**@rvagg**](https://github.com/rvagg))
### Added
- Add `BufferType` parameter to `abstract/put-get-del-test.js` for `bops` support ([**@rvagg**](https://github.com/rvagg))
- Add `isTypedArray` function which checks `ArrayBuffer` or `Uint8Array` for `bops` support ([**@rvagg**](https://github.com/rvagg))
### Fixed
- Fix `cleanup` function not calling back when browserified ([**@rvagg**](https://github.com/rvagg))
**Historical Note** It seems the version in `package.json` was never changed to `0.8.0` in the git history, even though the `0.8.0` tag exists. Most likely `package.json` was modified locally during `npm publish` but was never committed.
## [0.7.4] - 2013-08-02
### Fixed
- Fix problems related to `browserify` and `rimraf` ([**@rvagg**](https://github.com/rvagg))
## [0.7.3] - 2013-07-26
### Added
- Add [**@pgte**](https://github.com/pgte) to contributors ([**@rvagg**](https://github.com/rvagg))
- Test iterator with `limit` set to `-1` ([**@kesla**](https://github.com/kesla))
## [0.7.2] - 2013-07-08
### Changed
- Freeze chained batch state after `.write()` has been called ([**@rvagg**](https://github.com/rvagg))
- Make `NotFound` error case insensitive ([**@rvagg**](https://github.com/rvagg))
- Use `self` rather than binding functions to `this` ([**@juliangruber**](https://github.com/juliangruber))
### Added
- Add `AbstractChainedBatch#_checkWritten` ([**@rvagg**](https://github.com/rvagg))
- Test delete on non-existent key ([**@rvagg**](https://github.com/rvagg))
- Test iterator with `start` after database `end` ([**@juliangruber**](https://github.com/juliangruber))
### Fixed
- Don't coerce values to strings in browser ([**@maxogden**](https://github.com/maxogden))
- Make tests work in node and browser ([**@maxogden**](https://github.com/maxogden))
## [0.7.1] - 2013-05-15
### Changed
- Adjust tests to be browserable ([**@rvagg**](https://github.com/rvagg))
## [0.7.0] - 2013-05-14
### Added
- Add `AbstractChainedBatch#clear` ([**@rvagg**](https://github.com/rvagg))
## [0.6.1] - 2013-05-14
### Changed
- Make `AbstractIterator` call back with an error instead of throwing on nexting and ending ([**@mcollina**](https://github.com/mcollina))
## [0.6.0] - 2013-05-14
### Changed
- Split `t.deepEqual()` into multiple `t.equal()` in `abstract/iterator-test.js` ([**@rvagg**](https://github.com/rvagg))
- Make `AbstractIterator` call back with an error instead of throwing on nexting and ending ([**@mcollina**](https://github.com/mcollina))
## [0.5.0] - 2013-05-14
### Changed
- Make `iterator.end(cb)` and `iterator.next(cb)` call back with an error instead of throwing ([**@mcollina**](https://github.com/mcollina))
## [0.4.0] - 2013-05-14
### Changed
- Move `AbstractIterator` from `abstract-leveldown.js` to `abstract-iterator.js` ([**@rvagg**](https://github.com/rvagg))
### Added
- Add `AbstractChainedBatch` ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_chainedBatch` ([**@rvagg**](https://github.com/rvagg))
- Add `abstract/batch-test.js` and `abstract/chained-batch-test.js` ([**@rvagg**](https://github.com/rvagg))
## [0.4.0-1] - 2013-05-14
### Added
- Add [**@No9**](https://github.com/No9) and [**@mcollina**](https://github.com/mcollina) to contributors ([**@rvagg**](https://github.com/rvagg))
## [0.3.0] - 2013-05-04
### Changed
- Use `this._checkKeyValue()` instead of local function ([**@rvagg**](https://github.com/rvagg))
- Use `this._isBuffer()` instead of `Buffer.isBuffer()` ([**@rvagg**](https://github.com/rvagg))
### Added
- Restore test for opening the database without options ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_isBuffer` so it can be overridden ([**@rvagg**](https://github.com/rvagg))
- Add `AbstractLevelDOWN#_checkKeyValue` so it can be overridden ([**@rvagg**](https://github.com/rvagg))
## [0.2.3] - 2013-05-04
### Removed
- Remove test for opening the database without options ([**@rvagg**](https://github.com/rvagg))
## [0.2.2] - 2013-05-04
### Changed
- Split `.open()` tests into `.open()` and `.openAdvanced()` ([**@rvagg**](https://github.com/rvagg))
## [0.2.1] - 2013-05-04
### Changed
- Convert values to `string` in `abstract/put-get-del-test.js` if `Buffer` is `undefined` ([**@rvagg**](https://github.com/rvagg))
## [0.2.0] - 2013-05-04
### Changed
- Convert values to `string` in `abstract/get-test.js` if `Buffer` is `undefined` ([**@rvagg**](https://github.com/rvagg))
- Don't stringify keys and values in `abstract/iterator-test.js` ([**@maxogden**](https://github.com/maxogden))
### Added
- Add `process.browser` check for `start` and `end` keys in browser ([**@maxogden**](https://github.com/maxogden))
- Add `levelup` contributors ([**@rvagg**](https://github.com/rvagg))
### Fixed
- Fix `tape` compatibility issues ([**@maxogden**](https://github.com/maxogden))
## [0.1.0] - 2013-04-23
### Added
- Import abstract tests from `leveldown` ([**@maxogden**](https://github.com/maxogden))
### Fixed
- Clarify `README` ([**@rvagg**](https://github.com/rvagg))
## [0.0.2] - 2013-03-18
### Changed
- Export `checkKeyValue` ([**@rvagg**](https://github.com/rvagg))
### Added
- Add node 0.10 to Travis ([**@rvagg**](https://github.com/rvagg))
- Add `Buffer.isBuffer()` checks to keys and values ([**@rvagg**](https://github.com/rvagg))
## [0.0.1] - 2013-03-18
### Added
- Add `checkKeyValue` function for more complete error checking ([**@rvagg**](https://github.com/rvagg))
## 0.0.0 - 2013-03-15
First release. :seedling:
[6.2.2]: https://github.com/Level/abstract-leveldown/compare/v6.2.1...v6.2.2
[6.2.1]: https://github.com/Level/abstract-leveldown/compare/v6.2.0...v6.2.1
[6.2.0]: https://github.com/Level/abstract-leveldown/compare/v6.1.1...v6.2.0
[6.1.1]: https://github.com/Level/abstract-leveldown/compare/v6.1.0...v6.1.1
[6.1.0]: https://github.com/Level/abstract-leveldown/compare/v6.0.3...v6.1.0
[6.0.3]: https://github.com/Level/abstract-leveldown/compare/v6.0.2...v6.0.3
[6.0.2]: https://github.com/Level/abstract-leveldown/compare/v6.0.1...v6.0.2
[6.0.1]: https://github.com/Level/abstract-leveldown/compare/v6.0.0...v6.0.1
[6.0.0]: https://github.com/Level/abstract-leveldown/compare/v5.0.0...v6.0.0
[5.0.0]: https://github.com/Level/abstract-leveldown/compare/v4.0.3...v5.0.0
[4.0.3]: https://github.com/Level/abstract-leveldown/compare/v4.0.2...v4.0.3
[4.0.2]: https://github.com/Level/abstract-leveldown/compare/v4.0.1...v4.0.2
[4.0.1]: https://github.com/Level/abstract-leveldown/compare/v4.0.0...v4.0.1
[4.0.0]: https://github.com/Level/abstract-leveldown/compare/v3.0.0...v4.0.0
[3.0.0]: https://github.com/Level/abstract-leveldown/compare/v2.7.2...v3.0.0
[2.7.2]: https://github.com/Level/abstract-leveldown/compare/v2.7.1...v2.7.2
[2.7.1]: https://github.com/Level/abstract-leveldown/compare/v2.7.0...v2.7.1
[2.7.0]: https://github.com/Level/abstract-leveldown/compare/v2.6.3...v2.7.0
[2.6.3]: https://github.com/Level/abstract-leveldown/compare/v2.6.2...v2.6.3
[2.6.2]: https://github.com/Level/abstract-leveldown/compare/v2.6.1...v2.6.2
[2.6.1]: https://github.com/Level/abstract-leveldown/compare/v2.6.0...v2.6.1
[2.6.0]: https://github.com/Level/abstract-leveldown/compare/v2.5.0...v2.6.0
[2.5.0]: https://github.com/Level/abstract-leveldown/compare/v2.4.1...v2.5.0
[2.4.1]: https://github.com/Level/abstract-leveldown/compare/v2.4.0...v2.4.1
[2.4.0]: https://github.com/Level/abstract-leveldown/compare/v2.3.1...v2.4.0
[2.3.1]: https://github.com/Level/abstract-leveldown/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/Level/abstract-leveldown/compare/v2.2.2...v2.3.0
[2.2.2]: https://github.com/Level/abstract-leveldown/compare/v2.2.1...v2.2.2
[2.2.1]: https://github.com/Level/abstract-leveldown/compare/v2.2.0...v2.2.1
[2.2.0]: https://github.com/Level/abstract-leveldown/compare/v2.1.4...v2.2.0
[2.1.4]: https://github.com/Level/abstract-leveldown/compare/v2.1.3...v2.1.4
[2.1.3]: https://github.com/Level/abstract-leveldown/compare/v2.1.2...v2.1.3
[2.1.2]: https://github.com/Level/abstract-leveldown/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/Level/abstract-leveldown/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/Level/abstract-leveldown/compare/v2.0.3...v2.1.0
[2.0.3]: https://github.com/Level/abstract-leveldown/compare/v2.0.2...v2.0.3
[2.0.2]: https://github.com/Level/abstract-leveldown/compare/v2.0.1...v2.0.2
[2.0.1]: https://github.com/Level/abstract-leveldown/compare/v2.0.0...v2.0.1
[2.0.0]: https://github.com/Level/abstract-leveldown/compare/v1.0.0...v2.0.0
[1.0.0]: https://github.com/Level/abstract-leveldown/compare/v0.12.4...v1.0.0
[0.12.4]: https://github.com/Level/abstract-leveldown/compare/v0.12.3...v0.12.4
[0.12.3]: https://github.com/Level/abstract-leveldown/compare/v0.12.2...v0.12.3
[0.12.2]: https://github.com/Level/abstract-leveldown/compare/v0.12.1...v0.12.2
[0.12.1]: https://github.com/Level/abstract-leveldown/compare/v0.12.0...v0.12.1
[0.12.0]: https://github.com/Level/abstract-leveldown/compare/v0.11.4...v0.12.0
[0.11.4]: https://github.com/Level/abstract-leveldown/compare/v0.11.3...v0.11.4
[0.11.3]: https://github.com/Level/abstract-leveldown/compare/v0.11.2...v0.11.3
[0.11.2]: https://github.com/Level/abstract-leveldown/compare/0.11.1...v0.11.2
[0.11.1]: https://github.com/Level/abstract-leveldown/compare/0.11.0...0.11.1
[0.11.0]: https://github.com/Level/abstract-leveldown/compare/0.10.2...0.11.0
[0.10.2]: https://github.com/Level/abstract-leveldown/compare/0.10.1...0.10.2
[0.10.1]: https://github.com/Level/abstract-leveldown/compare/0.10.0...0.10.1
[0.10.0]: https://github.com/Level/abstract-leveldown/compare/0.9.0...0.10.0
[0.9.0]: https://github.com/Level/abstract-leveldown/compare/0.8.2...0.9.0
[0.8.2]: https://github.com/Level/abstract-leveldown/compare/0.8.1...0.8.2
[0.8.1]: https://github.com/Level/abstract-leveldown/compare/0.8.0...0.8.1
[0.8.0]: https://github.com/Level/abstract-leveldown/compare/0.7.4...0.8.0
[0.7.4]: https://github.com/Level/abstract-leveldown/compare/0.7.3...0.7.4
[0.7.3]: https://github.com/Level/abstract-leveldown/compare/0.7.2...0.7.3
[0.7.2]: https://github.com/Level/abstract-leveldown/compare/0.7.1...0.7.2
[0.7.1]: https://github.com/Level/abstract-leveldown/compare/0.7.0...0.7.1
[0.7.0]: https://github.com/Level/abstract-leveldown/compare/0.6.1...0.7.0
[0.6.1]: https://github.com/Level/abstract-leveldown/compare/0.6.0...0.6.1
[0.6.0]: https://github.com/Level/abstract-leveldown/compare/0.5.0...0.6.0
[0.5.0]: https://github.com/Level/abstract-leveldown/compare/0.4.0...0.5.0
[0.4.0]: https://github.com/Level/abstract-leveldown/compare/0.4.0-1...0.4.0
[0.4.0-1]: https://github.com/Level/abstract-leveldown/compare/0.3.0...0.4.0-1
[0.3.0]: https://github.com/Level/abstract-leveldown/compare/0.2.3...0.3.0
[0.2.3]: https://github.com/Level/abstract-leveldown/compare/0.2.2...0.2.3
[0.2.2]: https://github.com/Level/abstract-leveldown/compare/0.2.1...0.2.2
[0.2.1]: https://github.com/Level/abstract-leveldown/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/Level/abstract-leveldown/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/Level/abstract-leveldown/compare/0.0.2...0.1.0
[0.0.2]: https://github.com/Level/abstract-leveldown/compare/0.0.1...0.0.2
[0.0.1]: https://github.com/Level/abstract-leveldown/compare/0.0.0...0.0.1
abstract-leveldown-6.2.2/CONTRIBUTORS.md 0000664 0000000 0000000 00000007266 13553424167 0017625 0 ustar 00root root 0000000 0000000 # Contributors
| Name | GitHub | Social |
| :------------------------- | :----------------------------------------------------- | :----------------------------------------------------------------------- |
| **Rod Vagg** | [**@rvagg**](https://github.com/rvagg) | [**@rvagg@twitter**](https://twitter.com/rvagg) |
| **Vincent Weevers** | [**@vweevers**](https://github.com/vweevers) | [**@vweevers@twitter**](https://twitter.com/vweevers) |
| **Lars-Magnus Skog** | [**@ralphtheninja**](https://github.com/ralphtheninja) | [**@ralph@social.weho.st**](https://social.weho.st/@ralph) |
| **Julian Gruber** | [**@juliangruber**](https://github.com/juliangruber) | [**@juliangruber@twitter**](https://twitter.com/juliangruber) |
| **David Björklund** | [**@kesla**](https://github.com/kesla) | [**@david_bjorklund@twitter**](https://twitter.com/david_bjorklund) |
| **Max Ogden** | [**@maxogden**](https://github.com/maxogden) | [**@maxogden@twitter**](https://twitter.com/maxogden) |
| **Thomas Watson Steen** | | |
| **Alan Gutierrez** | [**@bigeasy**](https://github.com/bigeasy) | [**@bigeasy@twitter**](https://twitter.com/bigeasy) |
| **Dean Landolt** | [**@deanlandolt**](https://github.com/deanlandolt) | |
| **Calvin Metcalf** | [**@calvinmetcalf**](https://github.com/calvinmetcalf) | |
| **Meirion Hughes** | [**@MeirionHughes**](https://github.com/MeirionHughes) | |
| **Matteo Collina** | [**@mcollina**](https://github.com/mcollina) | [**@matteocollina@twitter**](https://twitter.com/matteocollina) |
| **Andrew Kelley** | [**@andrewrk**](https://github.com/andrewrk) | |
| **Tapani Moilanen** | [**@Tapppi**](https://github.com/Tapppi) | |
| **Dominic Tarr** | [**@dominictarr**](https://github.com/dominictarr) | [**@dominictarr@twitter**](https://twitter.com/dominictarr) |
| **Hao-kang Den** | | |
| **Kyle Robinson Young** | [**@shama**](https://github.com/shama) | [**@shamakry@twitter**](https://twitter.com/shamakry) |
| **Nathan Shively-Sanders** | [**@sandersn**](https://github.com/sandersn) | |
| **Nolan Lawson** | [**@nolanlawson**](https://github.com/nolanlawson) | [**@nolan@toot.cafe**](https://toot.cafe/@nolan) |
| **Tim Kuijsten** | [**@timkuijsten**](https://github.com/timkuijsten) | [**@timkuijsten@mastodon.social**](https://mastodon.social/@timkuijsten) |
| **Tim Oxley** | [**@timoxley**](https://github.com/timoxley) | [**@secoif@twitter**](https://twitter.com/secoif) |
abstract-leveldown-6.2.2/LICENSE.md 0000664 0000000 0000000 00000002145 13553424167 0016741 0 ustar 00root root 0000000 0000000 # The MIT License (MIT)
**Copyright © 2013-present Rod Vagg and [Contributors](CONTRIBUTORS.md).**
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
abstract-leveldown-6.2.2/README.md 0000664 0000000 0000000 00000073747 13553424167 0016634 0 ustar 00root root 0000000 0000000 # abstract-leveldown
> An abstract prototype matching the [`leveldown`][leveldown] API. Useful for extending [`levelup`](https://github.com/Level/levelup) functionality by providing a replacement to `leveldown`.
[![level badge][level-badge]](https://github.com/Level/awesome)
[](https://www.npmjs.com/package/abstract-leveldown)
[](https://www.npmjs.com/package/abstract-leveldown)
[](https://travis-ci.com/Level/abstract-leveldown)
[](https://coveralls.io/github/Level/abstract-leveldown)
[](https://standardjs.com)
[](https://www.npmjs.com/package/abstract-leveldown)
[](#backers)
[](#sponsors)
## Table of Contents
Click to expand
- [Background](#background)
- [Example](#example)
- [Browser Support](#browser-support)
- [Public API For Consumers](#public-api-for-consumers)
- [Private API For Implementors](#private-api-for-implementors)
- [Test Suite](#test-suite)
- [Spread The Word](#spread-the-word)
- [Install](#install)
- [Contributing](#contributing)
- [Big Thanks](#big-thanks)
- [Donate](#donate)
- [License](#license)
## Background
This module provides a simple base prototype for a key-value store. It has a public API for consumers and a private API for implementors. To implement a `abstract-leveldown` compliant store, extend its prototype and override the private underscore versions of the methods. For example, to implement `put()`, override `_put()` on your prototype.
Where possible, the default private methods have sensible _noop_ defaults that essentially do nothing. For example, `_open(callback)` will invoke `callback` on a next tick. Other methods like `_clear(..)` have functional defaults. Each method listed below documents whether implementing it is mandatory.
The private methods are always provided with consistent arguments, regardless of what is passed in through the public API. All public methods provide argument checking: if a consumer calls `open()` without a callback argument they'll get an `Error('open() requires a callback argument')`.
Where optional arguments are involved, private methods receive sensible defaults: a `get(key, callback)` call translates to `_get(key, options, callback)` where the `options` argument is an empty object. These arguments are documented below.
**If you are upgrading:** please see [UPGRADING.md](UPGRADING.md).
## Example
Let's implement a simplistic in-memory [`leveldown`][leveldown] replacement:
```js
var AbstractLevelDOWN = require('abstract-leveldown').AbstractLevelDOWN
var util = require('util')
// Constructor
function FakeLevelDOWN () {
AbstractLevelDOWN.call(this)
}
// Our new prototype inherits from AbstractLevelDOWN
util.inherits(FakeLevelDOWN, AbstractLevelDOWN)
FakeLevelDOWN.prototype._open = function (options, callback) {
// Initialize a memory storage object
this._store = {}
// Use nextTick to be a nice async citizen
process.nextTick(callback)
}
FakeLevelDOWN.prototype._serializeKey = function (key) {
// As an example, prefix all input keys with an exclamation mark.
// Below methods will receive serialized keys in their arguments.
return '!' + key
}
FakeLevelDOWN.prototype._put = function (key, value, options, callback) {
this._store[key] = value
process.nextTick(callback)
}
FakeLevelDOWN.prototype._get = function (key, options, callback) {
var value = this._store[key]
if (value === undefined) {
// 'NotFound' error, consistent with LevelDOWN API
return process.nextTick(callback, new Error('NotFound'))
}
process.nextTick(callback, null, value)
}
FakeLevelDOWN.prototype._del = function (key, options, callback) {
delete this._store[key]
process.nextTick(callback)
}
```
Now we can use our implementation with `levelup`:
```js
var levelup = require('levelup')
var db = levelup(new FakeLevelDOWN())
db.put('foo', 'bar', function (err) {
if (err) throw err
db.get('foo', function (err, value) {
if (err) throw err
console.log(value) // 'bar'
})
})
```
See [`memdown`](https://github.com/Level/memdown/) if you are looking for a complete in-memory replacement for `leveldown`.
## Browser Support
[](https://saucelabs.com/u/abstract-leveldown)
## Public API For Consumers
### `db = constructor(..)`
Constructors typically take a `location` argument pointing to a location on disk where the data will be stored. Since not all implementations are disk-based and some are non-persistent, implementors are free to take zero or more arguments in their constructor.
### `db.status`
A read-only property. An `abstract-leveldown` compliant store can be in one of the following states:
- `'new'` - newly created, not opened or closed
- `'opening'` - waiting for the store to be opened
- `'open'` - successfully opened the store, available for use
- `'closing'` - waiting for the store to be closed
- `'closed'` - store has been successfully closed, should not be used.
### `db.supports`
A read-only [manifest](https://github.com/Level/supports). Might be used like so:
```js
if (!db.supports.permanence) {
throw new Error('Persistent storage is required')
}
if (db.supports.bufferKeys && db.supports.promises) {
await db.put(Buffer.from('key'), 'value')
}
```
### `db.open([options, ]callback)`
Open the store. The `callback` function will be called with no arguments when the store has been successfully opened, or with a single error argument if the open operation failed for any reason.
The optional `options` argument may contain:
- `createIfMissing` _(boolean, default: `true`)_: If `true` and the store doesn't exist it will be created. If `false` and the store doesn't exist, `callback` will receive an error.
- `errorIfExists` _(boolean, default: `false`)_: If `true` and the store exists, `callback` will receive an error.
Not all implementations support the above options.
### `db.close(callback)`
Close the store. The `callback` function will be called with no arguments if the operation is successful or with a single `error` argument if closing failed for any reason.
### `db.get(key[, options], callback)`
Get a value from the store by `key`. The optional `options` object may contain:
- `asBuffer` _(boolean, default: `true`)_: Whether to return the `value` as a Buffer. If `false`, the returned type depends on the implementation.
The `callback` function will be called with an `Error` if the operation failed for any reason. If successful the first argument will be `null` and the second argument will be the value.
### `db.put(key, value[, options], callback)`
Store a new entry or overwrite an existing entry. There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the operation is successful or with an `Error` if putting failed for any reason.
### `db.del(key[, options], callback)`
Delete an entry. There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the operation is successful or with an `Error` if deletion failed for any reason.
### `db.batch(operations[, options], callback)`
Perform multiple _put_ and/or _del_ operations in bulk. The `operations` argument must be an `Array` containing a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation.
Each operation is contained in an object having the following properties: `type`, `key`, `value`, where the `type` is either `'put'` or `'del'`. In the case of `'del'` the `value` property is ignored.
There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the batch is successful or with an `Error` if the batch failed for any reason.
### `db.batch()`
Returns a [`chainedBatch`](#chainedbatch).
### `db.iterator([options])`
Returns an [`iterator`](#iterator). Accepts the following range options:
- `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be iterated. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries iterated will be the same.
- `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be iterated. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries iterated will be the same.
- `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
- Have no defined behavior (moving the concern to a higher level)
- Delegate to an underlying store (moving the concern to a lower level).
If you are an implementor, a final note: the [abstract test suite](#test-suite) does not test these types. Whether they are supported or how they sort is up to you; add custom tests accordingly.
In addition to range options, `iterator()` takes the following options:
- `keys` _(boolean, default: `true`)_: whether to return the key of each entry. If set to `false`, calls to `iterator.next(callback)` will yield keys with a value of `undefined`.
- `values` _(boolean, default: `true`)_: whether to return the value of each entry. If set to `false`, calls to `iterator.next(callback)` will yield values with a value of `undefined`.
- `keyAsBuffer` _(boolean, default: `true`)_: Whether to return the key of each entry as a Buffer. If `false`, the returned type depends on the implementation.
- `valueAsBuffer` _(boolean, default: `true`)_: Whether to return the value of each entry as a Buffer.
Lastly, an implementation is free to add its own options.
### `db.clear([options, ]callback)`
**This method is experimental. Not all implementations support it yet.**
Delete all entries or a range. Not guaranteed to be atomic. Accepts the following range options (with the same rules as on iterators):
- `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be deleted. Only entries where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries deleted will be the same.
- `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be deleted. Only entries where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the entries deleted will be the same.
- `reverse` _(boolean, default: `false`)_: delete entries in reverse order. Only effective in combination with `limit`, to remove the last N records.
- `limit` _(number, default: `-1`)_: limit the number of entries to be deleted. 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 deleted instead of the lowest keys.
If no options are provided, all entries will be deleted. The `callback` function will be called with no arguments if the operation was successful or with an `Error` if it failed for any reason.
### `chainedBatch`
#### `chainedBatch.put(key, value)`
Queue a `put` operation on this batch. This may throw if `key` or `value` is invalid.
#### `chainedBatch.del(key)`
Queue a `del` operation on this batch. This may throw if `key` is invalid.
#### `chainedBatch.clear()`
Clear all queued operations on this batch.
#### `chainedBatch.write([options, ]callback)`
Commit the queued operations for this batch. All operations will be written atomically, that is, they will either all succeed or fail with no partial commits.
There are no `options` by default but implementations may add theirs. The `callback` function will be called with no arguments if the batch is successful or with an `Error` if the batch failed for any reason.
After `write` has been called, no further operations are allowed.
#### `chainedBatch.db`
A reference to the `db` that created this chained batch.
### `iterator`
An iterator allows you to _iterate_ the entire store or a range. It operates on a snapshot of the store, created at the time `db.iterator()` was called. This means reads on the iterator are unaffected by simultaneous writes. Most but not all implementations can offer this guarantee.
An iterator keeps track of when a `next()` is in progress and when an `end()` has been called so it doesn't allow concurrent `next()` calls, it does allow `end()` while a `next()` is in progress and it doesn't allow either `next()` or `end()` after `end()` has been called.
#### `iterator.next(callback)`
Advance the iterator and yield the entry at that key. If an error occurs, the `callback` function will be called with an `Error`. Otherwise, the `callback` receives `null`, a `key` and a `value`. The type of `key` and `value` depends on the options passed to `db.iterator()`.
If the iterator has reached its end, both `key` and `value` will be `undefined`. This happens in the following situations:
- The end of the store has been reached
- The end of the range has been reached
- The last `iterator.seek()` was out of range.
**Note:** Don't forget to call `iterator.end()`, even if you received an error.
#### `iterator.seek(target)`
Seek the iterator to a given key or the closest key. Subsequent calls to `iterator.next()` will yield entries with keys equal to or larger than `target`, or equal to or smaller than `target` if the `reverse` option passed to `db.iterator()` was true.
If range options like `gt` were passed to `db.iterator()` and `target` does not fall within that range, the iterator will reach its end.
**Note:** At the time of writing, [`leveldown`][leveldown] is the only known implementation to support `seek()`. In other implementations, it is a noop.
#### `iterator.end(callback)`
End iteration and free up underlying resources. The `callback` function will be called with no arguments on success or with an `Error` if ending failed for any reason.
#### `iterator.db`
A reference to the `db` that created this iterator.
### Type Support
The following applies to any method above that takes a `key` argument or option: all implementations _must_ support a `key` of type String and _should_ support a `key` of type Buffer. A `key` may not be `null`, `undefined`, a zero-length Buffer, zero-length string or zero-length array.
The following applies to any method above that takes a `value` argument or option: all implementations _must_ support a `value` of type String or Buffer. A `value` may not be `null` or `undefined` due to preexisting significance in streams and iterators.
Support of other key and value types depends on the implementation as well as its underlying storage. See also [`db._serializeKey`](#db_serializekeykey) and [`db._serializeValue`](#db_serializevaluevalue).
## Private API For Implementors
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(callback, ..)`, `setImmediate` or some other means of micro- or macrotask scheduling.
### `db = AbstractLevelDOWN([manifest])`
The constructor. Sets the `.status` to `'new'`. Optionally takes a [manifest](https://github.com/Level/supports) object which `abstract-leveldown` will enrich:
```js
AbstractLevelDOWN.call(this, {
bufferKeys: true,
snapshots: true,
// ..
})
```
### `db._open(options, callback)`
Open the store. The `options` object will always have the following properties: `createIfMissing`, `errorIfExists`. If opening failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_open()` is a sensible noop and invokes `callback` on a next tick.
### `db._close(callback)`
Close the store. If closing failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_close()` is a sensible noop and invokes `callback` on a next tick.
### `db._serializeKey(key)`
Convert a `key` to a type supported by the underlying storage. All methods below that take a `key` argument or option - including `db._iterator()` with its range options and `iterator._seek()` with its `target` argument - will receive serialized keys. For example, if `_serializeKey` is implemented as:
```js
FakeLevelDOWN.prototype._serializeKey = function (key) {
return Buffer.isBuffer(key) ? key : String(key)
}
```
Then `db.get(2, callback)` translates into `db._get('2', options, callback)`. Similarly, `db.iterator({ gt: 2 })` translates into `db._iterator({ gt: '2', ... })` and `iterator.seek(2)` translates into `iterator._seek('2')`.
If the underlying storage supports any JavaScript type or if your implementation wraps another implementation, it is recommended to make `_serializeKey` an identity function (returning the key as-is). Serialization is irreversible, unlike _encoding_ as performed by implementations like [`encoding-down`][encoding-down]. This also applies to `_serializeValue`.
The default `_serializeKey()` is an identity function.
### `db._serializeValue(value)`
Convert a `value` to a type supported by the underlying storage. All methods below that take a `value` argument or option will receive serialized values. For example, if `_serializeValue` is implemented as:
```js
FakeLevelDOWN.prototype._serializeValue = function (value) {
return Buffer.isBuffer(value) ? value : String(value)
}
```
Then `db.put(key, 2, callback)` translates into `db._put(key, '2', options, callback)`.
The default `_serializeValue()` is an identity function.
### `db._get(key, options, callback)`
Get a value by `key`. The `options` object will always have the following properties: `asBuffer`. If the key does not exist, call the `callback` function with a `new Error('NotFound')`. Otherwise call `callback` with `null` as the first argument and the value as the second.
The default `_get()` invokes `callback` on a next tick with a `NotFound` error. It must be overridden.
### `db._put(key, value, options, callback)`
Store a new entry or overwrite an existing entry. There are no default options but `options` will always be an object. If putting failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_put()` invokes `callback` on a next tick. It must be overridden.
### `db._del(key, options, callback)`
Delete an entry. There are no default options but `options` will always be an object. If deletion failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_del()` invokes `callback` on a next tick. It must be overridden.
### `db._batch(operations, options, callback)`
Perform multiple _put_ and/or _del_ operations in bulk. The `operations` argument is always an `Array` containing a list of operations to be executed sequentially, although as a whole they should be performed as an atomic operation. Each operation is guaranteed to have at least `type` and `key` properties. There are no default options but `options` will always be an object. If the batch failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_batch()` invokes `callback` on a next tick. It must be overridden.
### `db._chainedBatch()`
The default `_chainedBatch()` returns a functional `AbstractChainedBatch` instance that uses `db._batch(array, options, callback)` under the hood. The prototype is available on the main exports for you to extend. If you want to implement chainable batch operations in a different manner then you should extend `AbstractChainedBatch` and return an instance of this prototype in the `_chainedBatch()` method:
```js
var AbstractChainedBatch = require('abstract-leveldown').AbstractChainedBatch
var inherits = require('util').inherits
function ChainedBatch (db) {
AbstractChainedBatch.call(this, db)
}
inherits(ChainedBatch, AbstractChainedBatch)
FakeLevelDOWN.prototype._chainedBatch = function () {
return new ChainedBatch(this)
}
```
### `db._iterator(options)`
The default `_iterator()` returns a noop `AbstractIterator` instance. It must be overridden, by extending `AbstractIterator` (available on the main module exports) and returning an instance of this prototype in the `_iterator(options)` method.
The `options` object will always have the following properties: `reverse`, `keys`, `values`, `limit`, `keyAsBuffer` and `valueAsBuffer`.
### `db._clear(options, callback)`
**This method is experimental and optional for the time being. To enable its tests, set the [`clear` option of the test suite](#excluding-tests) to `true`.**
Delete all entries or a range. Does not have to be atomic. It is recommended (and possibly mandatory in the future) to operate on a snapshot so that writes scheduled after a call to `clear()` will not be affected.
The default `_clear()` uses `_iterator()` and `_del()` to provide a reasonable fallback, but requires binary key support. It is _recommended_ to implement `_clear()` with more performant primitives than `_iterator()` and `_del()` if the underlying storage has such primitives. Implementations that don't support binary keys _must_ implement their own `_clear()`.
Implementations that wrap another `db` can typically forward the `_clear()` call to that `db`, having transformed range options if necessary.
The `options` object will always have the following properties: `reverse` and `limit`.
### `iterator = AbstractIterator(db)`
The first argument to this constructor must be an instance of your `AbstractLevelDOWN` implementation. The constructor will set `iterator.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.
#### `iterator._next(callback)`
Advance the iterator and yield the entry at that key. If nexting failed, call the `callback` function with an `Error`. Otherwise, call `callback` with `null`, a `key` and a `value`.
The default `_next()` invokes `callback` on a next tick. It must be overridden.
#### `iterator._seek(target)`
Seek the iterator to a given key or the closest key. This method is optional.
#### `iterator._end(callback)`
Free up underlying resources. This method is guaranteed to only be called once. If ending failed, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
The default `_end()` invokes `callback` on a next tick. Overriding is optional.
### `chainedBatch = AbstractChainedBatch(db)`
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)`
Queue a `put` operation on this batch.
#### `chainedBatch._del(key)`
Queue a `del` operation on this batch.
#### `chainedBatch._clear()`
Clear all queued operations on this batch.
#### `chainedBatch._write(options, callback)`
The default `_write` method uses `db._batch`. If the `_write` method is overridden it must atomically commit the queued operations. There are no default options but `options` will always be an object. If committing fails, call the `callback` function with an `Error`. Otherwise call `callback` without any arguments.
## Test Suite
To prove that your implementation is `abstract-leveldown` compliant, include the abstract test suite in your `test.js` (or similar):
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN()
}
})
```
This is the most minimal setup. The `test` option _must_ be a function that is API-compatible with `tape`. The `factory` option _must_ be a function that returns a unique and isolated database instance. The factory will be called many times by the test suite.
If your implementation is disk-based we recommend using [`tempy`](https://github.com/sindresorhus/tempy) (or similar) to create unique temporary directories. Your setup could look something like:
```js
const test = require('tape')
const tempy = require('tempy')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN(tempy.directory())
}
})
```
### Excluding tests
As not every implementation can be fully compliant due to limitations of its underlying storage, some tests may be skipped. For example, to skip snapshot tests:
```js
suite({
// ..
snapshots: false
})
```
This also serves as a signal to users of your implementation. The following options are available:
- `bufferKeys`: set to `false` if binary keys are not supported by the underlying storage
- `seek`: set to `false` if your `iterator` does not implement `_seek`
- `clear`: defaults to `false` until a next major release. Set to `true` if your implementation either implements `_clear()` itself or is suitable to use the default implementation of `_clear()` (which requires binary key support).
- `snapshots`: set to `false` if any of the following is true:
- 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.
This metadata will be moved to manifests (`db.supports`) in the future.
### Setup and teardown
To perform (a)synchronous work before or after each test, you may define `setUp` and `tearDown` functions:
```js
suite({
// ..
setUp: function (t) {
t.end()
},
tearDown: function (t) {
t.end()
}
})
```
### Reusing `testCommon`
The input to the test suite is a `testCommon` object. Should you need to reuse `testCommon` for your own (additional) tests, use the included utility to create a `testCommon` with defaults:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
const testCommon = suite.common({
test: test,
factory: function () {
return new YourDOWN()
}
})
suite(testCommon)
```
The `testCommon` object will have all the properties describe above: `test`, `factory`, `setUp`, `tearDown` and the skip options. You might use it like so:
```js
test('setUp', testCommon.setUp)
test('custom test', function (t) {
var db = testCommon.factory()
// ..
})
test('another custom test', function (t) {
var db = testCommon.factory()
// ..
})
test('tearDown', testCommon.tearDown)
```
## Spread The Word
If you'd like to share your awesome implementation with the world, here's what you might want to do:
- Add an awesome badge to your `README`: ``
- Publish your awesome module to [npm](https://npmjs.org)
- Send a Pull Request to [Level/awesome](https://github.com/Level/awesome) to advertise your work!
## Install
With [npm](https://npmjs.org) do:
```
npm install abstract-leveldown
```
## Contributing
[`Level/abstract-leveldown`](https://github.com/Level/abstract-leveldown) is an **OPEN Open Source Project**. This means that:
> Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.
See the [Contribution Guide](https://github.com/Level/community/blob/master/CONTRIBUTING.md) for more details.
## Big Thanks
Cross-browser Testing Platform and Open Source ♥ Provided by [Sauce Labs](https://saucelabs.com).
[](https://saucelabs.com)
## Donate
To sustain [`Level`](https://github.com/Level) and its activities, become a backer or sponsor on [Open Collective](https://opencollective.com/level). Your logo or avatar will be displayed on our 28+ [GitHub repositories](https://github.com/Level) and [npm](https://www.npmjs.com/) packages. 💖
### Backers
[](https://opencollective.com/level)
### Sponsors
[](https://opencollective.com/level)
## License
[MIT](LICENSE.md) © 2013-present Rod Vagg and [Contributors](CONTRIBUTORS.md).
[level-badge]: https://leveljs.org/img/badge.svg
[encoding-down]: https://github.com/Level/encoding-down
[leveldown]: https://github.com/Level/leveldown
abstract-leveldown-6.2.2/UPGRADING.md 0000664 0000000 0000000 00000026365 13553424167 0017211 0 ustar 00root root 0000000 0000000 # Upgrade Guide
This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the [changelog](CHANGELOG.md).
## Table of Contents
Click to expand
- [v6](#v6)
- [v5](#v5)
- [v4](#v4)
- [v3](#v3)
## v6
This release brings a major refactoring of the test suite, decouples `abstract-leveldown` from disk-based implementations and solves long-standing issues around serialization and type support. Because the changes are substantial, this guide has two sections:
1. **Changes to public API** - for consumers of any implementation.
2. **Changes to private API** - intended for implementors.
### Changes to public API
#### Nullish values are rejected
In addition to rejecting `null` and `undefined` as _keys_, `abstract-leveldown` now also rejects these types as _values_, due to preexisting significance in streams and iterators.
Before this, the behavior of these types depended on a large number of factors: `_serializeValue` and type support of the underlying storage, whether `get()`, `iterator()` or a stream was used to retrieve values, the `keys` and `asBuffer` options of `iterator()` and finally, which encoding was selected.
#### Range options are serialized
Previously, range options like `lt` were passed through as-is, unlike keys.
#### The rules for range options have been relaxed
Because `null`, `undefined`, zero-length strings and zero-length buffers are significant types in encodings like `bytewise` and `charwise`, they became valid as range options. In fact, any type is now valid. This means `db.iterator({ gt: undefined })` is not the same as `db.iterator({})`.
Furthermore, `abstract-leveldown` makes no assumptions about the meaning of these types. Range tests that assumed `null` meant "not defined" have been removed.
#### Zero-length array keys are rejected
Though this was already the case because `_checkKey` stringified its input before checking the length, that behavior has been replaced with an explicit `Array.isArray()` check and a new error message.
#### No longer assumes support of boolean and `NaN` keys
A test that asserted boolean and `NaN` keys were valid has been removed.
#### Browser support
IE10 has been dropped.
### Changes to private API
#### `location` was removed
`AbstractLevelDOWN` is no longer associated with a `location`. It's up to the implementation to handle it if it's required.
If your implementation has a `location` and you previously did:
```js
function YourDOWN (location) {
AbstractLevelDOWN.call(this, location)
}
```
You must now do:
```js
function YourDOWN (location) {
this.location = location
AbstractLevelDOWN.call(this)
}
```
Be sure to include appropriate type checks. If you relied on the default `AbstractLevelDOWN` behavior that would be:
```js
if (typeof location !== 'string') {
throw new Error('constructor requires a location string argument')
}
```
#### Abstract test suite has moved to a single entry point
Instead of including test files individually, you can and should include the test suite with one `require()` statement. If you previously did:
```js
const test = require('tape')
const testCommon = require('abstract-leveldown/testCommon')
const YourDOWN = require('.')
require('abstract-leveldown/abstract/get-test').all(YourDOWN, test, testCommon)
require('abstract-leveldown/abstract/put-test').all(YourDOWN, test, testCommon)
// etc
```
You must now do:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN()
}
})
```
The input to the test suite is a new form of `testCommon`. Should you need to reuse `testCommon` for your own (additional) tests, use the included utility to create a `testCommon` with defaults:
```js
const test = require('tape')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
const testCommon = suite.common({
test: test,
factory: function () {
return new YourDOWN()
}
})
suite(testCommon)
```
As part of removing `location`, the abstract tests no longer use `testCommon.location()`. Instead an implementation _must_ implement `factory()` which _must_ return a unique and isolated database instance. This allows implementations to pass options to their constructor.
The `testCommon.cleanup` method has been removed. Because `factory()` returns a unique database instance, cleanup should no longer be necessary. The `testCommon.lastLocation` method has also been removed as there is no remaining use of it in abstract tests.
Previously, implementations using the default `testCommon` had to include `rimraf` in their `devDependencies` and browser-based implementations had to exclude `rimraf` from browserify builds. This is no longer the case.
If your implementation is disk-based we recommend using [`tempy`](https://github.com/sindresorhus/tempy) (or similar) to create unique temporary directories. Together with `factory()` your setup could now look something like:
```js
const test = require('tape')
const tempy = require('tempy')
const suite = require('abstract-leveldown/test')
const YourDOWN = require('.')
suite({
test: test,
factory: function () {
return new YourDOWN(tempy.directory())
}
})
```
#### The `collectEntries` utility has moved
The `testCommon.collectEntries` method has moved to the npm package `level-concat-iterator`. If your (additional) tests depend on `collectEntries` and you previously did:
```js
testCommon.collectEntries(iterator, function (err, entries) {})
```
You must now do:
```js
const concat = require('level-concat-iterator')
concat(iterator, function (err, entries) {})
```
#### Setup and teardown became noops
Because cleanup is no longer necessary, the `testCommon.setUp` and `testCommon.tearDown` methods are now noops by default. If you do need to perform (a)synchronous work before or after each test, `setUp` and `tearDown` can be overridden:
```js
suite({
// ..
setUp: function (t) {
t.end()
},
tearDown: function (t) {
t.end()
}
})
```
#### Optional tests have been separated
If your implementation does not support snapshots or other optional features, the relevant tests may be skipped. For example:
```js
suite({
// ..
snapshots: false
})
```
Please see the [README](README.md) for a list of options. Note that some of these have replaced `process.browser` checks.
#### Iterator must have a `db` reference
The `db` argument of the `AbstractIterator` constructor became mandatory, as well as a public `db` property on the instance. Its existence is not new; the test suite now asserts that your implementation also has it.
#### Seeking became part of official API
If your implementation previously defined the public `iterator.seek(target)`, it must now define the private `iterator._seek(target)`. The new public API is equal to the reference implementation of `leveldown` except for two differences:
- The `target` argument is not type checked, this is up to the implementation.
- The `target` argument is passed through `db._serializeKey`.
Please see the [README](README.md) for details.
#### Chained batch has been refactored
- The default `_clear` method is no longer a noop; instead it clears the operations queued by `_put` and/or `_del`
- The `_write` method now takes an `options` object as its first argument
- The `db` argument of the `AbstractChainedBatch` constructor became mandatory, as well as a public `db` property on the instance, which was previously named `_db`.
#### Default `_serializeKey` and `_serializeValue` became identity functions
They return whatever is given. Previously they were opinionated and mostly geared towards string- and Buffer-based storages. Implementations that didn't already define their own serialization should now do so, according to the types that they support. Please refer to the [README](README.md) for recommended behavior.
## v5
Dropped support for node 4. No other breaking changes.
## v4
#### default `testCommon` parameter
The `testCommon` parameter will now default to `abstract-leveldown/testCommon.js`. You can omit this parameter, unless your implementation needs a custom version.
If your code today looks something like:
```js
const test = require('tape')
const testCommon = require('abstract-leveldown/testCommon')
const leveldown = require('./your-leveldown')
const abstract = require('abstract-leveldown/abstract/get-test')
abstract.all(leveldown, test, testCommon)
```
You can simplify it to:
```js
const test = require('tape')
const leveldown = require('./your-leveldown')
const abstract = require('abstract-leveldown/abstract/get-test')
abstract.all(leveldown, test)
```
#### `testBuffer` parameter removed
The `abstract/put-get-del-test.js` previously took a custom `testBuffer` parameter. After an [analysis](https://github.com/Level/abstract-leveldown/pull/175#issuecomment-353867144) of various implementations we came to the conclusion that the parameter has no use.
If your implementation is using this abstract test, change from:
```js
const test = require('tape')
const testCommon = require('abstract-leveldown/testCommon')
const leveldown = require('./your-leveldown')
const fs = require('fs')
const path = require('path')
const testBuffer = fs.readFileSync(path.join(__dirname, 'data/testdata.bin'))
const abstract = require('abstract-leveldown/abstract/put-get-del-test')
abstract.all(leveldown, test, testBuffer, testCommon)
```
to:
```js
const test = require('tape')
const testCommon = require('abstract-leveldown/testCommon')
const leveldown = require('./your-leveldown')
const abstract = require('abstract-leveldown/abstract/put-get-del-test')
abstract.all(leveldown, test, testCommon)
```
or if `testCommon` is also redundant, to:
```js
const test = require('tape')
const leveldown = require('./your-leveldown')
const abstract = require('abstract-leveldown/abstract/put-get-del-test')
abstract.all(leveldown, test)
```
#### `.approximateSize` method removed
The `.approximateSize` method has been removed from the public API. It is heavily related to `LevelDB` and more often than not, other stores lack the native primitives to implement this. If you did implement the internal `_approximateSize` method, that is now dead code. To preserve the method in your public API, rename it to `approximateSize` and also take care of the initialization code. Look to `leveldown` for inspiration.
Also, the corresponding abstract tests have been removed, so your implementation can no longer require `abstract/approximate-size-test`.
#### `._isBuffer` method removed
Because `Buffer` is available in all environments nowadays, there is no need for alternatives like typed arrays. It is preferred to use `Buffer` and `Buffer.isBuffer()` directly.
#### `isLevelDOWN` function removed
This was a legacy function.
#### `ranges-test.js` renamed
We have refactored a lot of the tests. Specifically the iterator tests were split in two and in that process we renamed `ranges-test.js` to `iterator-range-test.js`.
If your implementation is using these tests then change from:
```js
const abstract = require('abstract-leveldown/abstract/ranges-test')
```
to:
```js
const abstract = require('abstract-leveldown/abstract/iterator-range-test')
```
## v3
No changes to the API. New major version because support for node 0.12 was dropped.
abstract-leveldown-6.2.2/abstract-chained-batch.js 0000664 0000000 0000000 00000003532 13553424167 0022147 0 ustar 00root root 0000000 0000000 function AbstractChainedBatch (db) {
if (typeof db !== 'object' || db === null) {
throw new TypeError('First argument must be an abstract-leveldown compliant store')
}
this.db = db
this._operations = []
this._written = false
}
AbstractChainedBatch.prototype._checkWritten = function () {
if (this._written) {
throw new Error('write() already called on this batch')
}
}
AbstractChainedBatch.prototype.put = function (key, value) {
this._checkWritten()
var 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)
return this
}
AbstractChainedBatch.prototype._put = function (key, value) {
this._operations.push({ type: 'put', key: key, value: value })
}
AbstractChainedBatch.prototype.del = function (key) {
this._checkWritten()
var err = this.db._checkKey(key)
if (err) throw err
key = this.db._serializeKey(key)
this._del(key)
return this
}
AbstractChainedBatch.prototype._del = function (key) {
this._operations.push({ type: 'del', key: key })
}
AbstractChainedBatch.prototype.clear = function () {
this._checkWritten()
this._clear()
return this
}
AbstractChainedBatch.prototype._clear = function () {
this._operations = []
}
AbstractChainedBatch.prototype.write = function (options, callback) {
this._checkWritten()
if (typeof options === 'function') { callback = options }
if (typeof callback !== 'function') {
throw new Error('write() requires a callback argument')
}
if (typeof options !== 'object' || options === null) {
options = {}
}
this._written = true
this._write(options, callback)
}
AbstractChainedBatch.prototype._write = function (options, callback) {
this.db._batch(this._operations, options, callback)
}
module.exports = AbstractChainedBatch
abstract-leveldown-6.2.2/abstract-iterator.js 0000664 0000000 0000000 00000003235 13553424167 0021326 0 ustar 00root root 0000000 0000000 function AbstractIterator (db) {
if (typeof db !== 'object' || db === null) {
throw new TypeError('First argument must be an abstract-leveldown compliant store')
}
this.db = db
this._ended = false
this._nexting = false
}
AbstractIterator.prototype.next = function (callback) {
var self = this
if (typeof callback !== 'function') {
throw new Error('next() requires a callback argument')
}
if (self._ended) {
process.nextTick(callback, new Error('cannot call next() after end()'))
return self
}
if (self._nexting) {
process.nextTick(callback, new Error('cannot call next() before previous next() has completed'))
return self
}
self._nexting = true
self._next(function () {
self._nexting = false
callback.apply(null, arguments)
})
return self
}
AbstractIterator.prototype._next = function (callback) {
process.nextTick(callback)
}
AbstractIterator.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')
}
target = this.db._serializeKey(target)
this._seek(target)
}
AbstractIterator.prototype._seek = function (target) {}
AbstractIterator.prototype.end = function (callback) {
if (typeof callback !== 'function') {
throw new Error('end() requires a callback argument')
}
if (this._ended) {
return process.nextTick(callback, new Error('end() already called on iterator'))
}
this._ended = true
this._end(callback)
}
AbstractIterator.prototype._end = function (callback) {
process.nextTick(callback)
}
module.exports = AbstractIterator
abstract-leveldown-6.2.2/abstract-leveldown.js 0000664 0000000 0000000 00000020616 13553424167 0021476 0 ustar 00root root 0000000 0000000 var xtend = require('xtend')
var supports = require('level-supports')
var AbstractIterator = require('./abstract-iterator')
var AbstractChainedBatch = require('./abstract-chained-batch')
var hasOwnProperty = Object.prototype.hasOwnProperty
var rangeOptions = 'start end gt gte lt lte'.split(' ')
function AbstractLevelDOWN (manifest) {
this.status = 'new'
// TODO (next major): make this mandatory
this.supports = supports(manifest, {
status: true
})
}
AbstractLevelDOWN.prototype.open = function (options, callback) {
var self = this
var oldStatus = this.status
if (typeof options === 'function') callback = options
if (typeof callback !== 'function') {
throw new Error('open() requires a callback argument')
}
if (typeof options !== 'object' || options === null) options = {}
options.createIfMissing = options.createIfMissing !== false
options.errorIfExists = !!options.errorIfExists
this.status = 'opening'
this._open(options, function (err) {
if (err) {
self.status = oldStatus
return callback(err)
}
self.status = 'open'
callback()
})
}
AbstractLevelDOWN.prototype._open = function (options, callback) {
process.nextTick(callback)
}
AbstractLevelDOWN.prototype.close = function (callback) {
var self = this
var oldStatus = this.status
if (typeof callback !== 'function') {
throw new Error('close() requires a callback argument')
}
this.status = 'closing'
this._close(function (err) {
if (err) {
self.status = oldStatus
return callback(err)
}
self.status = 'closed'
callback()
})
}
AbstractLevelDOWN.prototype._close = function (callback) {
process.nextTick(callback)
}
AbstractLevelDOWN.prototype.get = function (key, options, callback) {
if (typeof options === 'function') callback = options
if (typeof callback !== 'function') {
throw new Error('get() requires a callback argument')
}
var err = this._checkKey(key)
if (err) return process.nextTick(callback, err)
key = this._serializeKey(key)
if (typeof options !== 'object' || options === null) options = {}
options.asBuffer = options.asBuffer !== false
this._get(key, options, callback)
}
AbstractLevelDOWN.prototype._get = function (key, options, callback) {
process.nextTick(function () { callback(new Error('NotFound')) })
}
AbstractLevelDOWN.prototype.put = function (key, value, options, callback) {
if (typeof options === 'function') callback = options
if (typeof callback !== 'function') {
throw new Error('put() requires a callback argument')
}
var err = this._checkKey(key) || this._checkValue(value)
if (err) return process.nextTick(callback, err)
key = this._serializeKey(key)
value = this._serializeValue(value)
if (typeof options !== 'object' || options === null) options = {}
this._put(key, value, options, callback)
}
AbstractLevelDOWN.prototype._put = function (key, value, options, callback) {
process.nextTick(callback)
}
AbstractLevelDOWN.prototype.del = function (key, options, callback) {
if (typeof options === 'function') callback = options
if (typeof callback !== 'function') {
throw new Error('del() requires a callback argument')
}
var err = this._checkKey(key)
if (err) return process.nextTick(callback, err)
key = this._serializeKey(key)
if (typeof options !== 'object' || options === null) options = {}
this._del(key, options, callback)
}
AbstractLevelDOWN.prototype._del = function (key, options, callback) {
process.nextTick(callback)
}
AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
if (!arguments.length) return this._chainedBatch()
if (typeof options === 'function') callback = options
if (typeof array === 'function') callback = array
if (typeof callback !== 'function') {
throw new Error('batch(array) requires a callback argument')
}
if (!Array.isArray(array)) {
return process.nextTick(callback, new Error('batch(array) requires an array argument'))
}
if (array.length === 0) {
return process.nextTick(callback)
}
if (typeof options !== 'object' || options === null) options = {}
var serialized = new Array(array.length)
for (var i = 0; i < array.length; i++) {
if (typeof array[i] !== 'object' || array[i] === null) {
return process.nextTick(callback, new Error('batch(array) element must be an object and not `null`'))
}
var e = xtend(array[i])
if (e.type !== 'put' && e.type !== 'del') {
return process.nextTick(callback, new Error("`type` must be 'put' or 'del'"))
}
var err = this._checkKey(e.key)
if (err) return process.nextTick(callback, err)
e.key = this._serializeKey(e.key)
if (e.type === 'put') {
var valueErr = this._checkValue(e.value)
if (valueErr) return process.nextTick(callback, valueErr)
e.value = this._serializeValue(e.value)
}
serialized[i] = e
}
this._batch(serialized, options, callback)
}
AbstractLevelDOWN.prototype._batch = function (array, options, callback) {
process.nextTick(callback)
}
AbstractLevelDOWN.prototype.clear = function (options, callback) {
if (typeof options === 'function') {
callback = options
} else if (typeof callback !== 'function') {
throw new Error('clear() requires a callback argument')
}
options = cleanRangeOptions(this, options)
options.reverse = !!options.reverse
options.limit = 'limit' in options ? options.limit : -1
this._clear(options, callback)
}
AbstractLevelDOWN.prototype._clear = function (options, callback) {
// Avoid setupIteratorOptions, would serialize range options a second time.
options.keys = true
options.values = false
options.keyAsBuffer = true
options.valueAsBuffer = true
var iterator = this._iterator(options)
var emptyOptions = {}
var self = this
var next = function (err) {
if (err) {
return iterator.end(function () {
callback(err)
})
}
iterator.next(function (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)
})
}
next()
}
AbstractLevelDOWN.prototype._setupIteratorOptions = function (options) {
options = cleanRangeOptions(this, options)
options.reverse = !!options.reverse
options.keys = options.keys !== false
options.values = options.values !== false
options.limit = 'limit' in options ? options.limit : -1
options.keyAsBuffer = options.keyAsBuffer !== false
options.valueAsBuffer = options.valueAsBuffer !== false
return options
}
function cleanRangeOptions (db, options) {
var result = {}
for (var k in options) {
if (!hasOwnProperty.call(options, k)) continue
var opt = options[k]
if (isRangeOption(k)) {
// Note that we don't reject nullish and empty options here. While
// those types are invalid as keys, they are valid as range options.
opt = db._serializeKey(opt)
}
result[k] = opt
}
return result
}
function isRangeOption (k) {
return rangeOptions.indexOf(k) !== -1
}
AbstractLevelDOWN.prototype.iterator = function (options) {
if (typeof options !== 'object' || options === null) options = {}
options = this._setupIteratorOptions(options)
return this._iterator(options)
}
AbstractLevelDOWN.prototype._iterator = function (options) {
return new AbstractIterator(this)
}
AbstractLevelDOWN.prototype._chainedBatch = function () {
return new AbstractChainedBatch(this)
}
AbstractLevelDOWN.prototype._serializeKey = function (key) {
return key
}
AbstractLevelDOWN.prototype._serializeValue = function (value) {
return 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) {
return new Error('key cannot be an empty Buffer')
} else if (key === '') {
return new Error('key cannot be an empty String')
} else if (Array.isArray(key) && key.length === 0) {
return new Error('key cannot be an empty Array')
}
}
AbstractLevelDOWN.prototype._checkValue = function (value) {
if (value === null || value === undefined) {
return new Error('value cannot be `null` or `undefined`')
}
}
module.exports = AbstractLevelDOWN
abstract-leveldown-6.2.2/index.js 0000664 0000000 0000000 00000000271 13553424167 0017000 0 ustar 00root root 0000000 0000000 exports.AbstractLevelDOWN = require('./abstract-leveldown')
exports.AbstractIterator = require('./abstract-iterator')
exports.AbstractChainedBatch = require('./abstract-chained-batch')
abstract-leveldown-6.2.2/package.json 0000664 0000000 0000000 00000002450 13553424167 0017622 0 ustar 00root root 0000000 0000000 {
"name": "abstract-leveldown",
"version": "6.2.2",
"description": "An abstract prototype matching the LevelDOWN API",
"license": "MIT",
"main": "index.js",
"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",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"hallmark": "hallmark --fix",
"dependency-check": "dependency-check . test/*.js",
"prepublishOnly": "npm run dependency-check"
},
"dependencies": {
"level-concat-iterator": "~2.0.0",
"level-supports": "~1.0.0",
"xtend": "~4.0.0"
},
"devDependencies": {
"airtap": "^2.0.0",
"coveralls": "^3.0.2",
"dependency-check": "^3.3.0",
"hallmark": "^2.0.0",
"level-community": "^3.0.0",
"nyc": "^14.0.0",
"sinon": "^7.2.4",
"standard": "^14.0.0",
"tape": "^4.10.0"
},
"hallmark": {
"community": "level-community"
},
"repository": {
"type": "git",
"url": "https://github.com/Level/abstract-leveldown.git"
},
"homepage": "https://github.com/Level/abstract-leveldown",
"keywords": [
"level",
"leveldb",
"leveldown",
"levelup"
],
"engines": {
"node": ">=6"
}
}
abstract-leveldown-6.2.2/sauce-labs.svg 0000664 0000000 0000000 00000012427 13553424167 0020101 0 ustar 00root root 0000000 0000000
abstract-leveldown-6.2.2/test/ 0000775 0000000 0000000 00000000000 13553424167 0016312 5 ustar 00root root 0000000 0000000 abstract-leveldown-6.2.2/test/batch-test.js 0000664 0000000 0000000 00000020643 13553424167 0020713 0 ustar 00root root 0000000 0000000 var db
var verifyNotFoundError = require('./util').verifyNotFoundError
var isTypedArray = require('./util').isTypedArray
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test callback-less, 2-arg, batch() throws', function (t) {
t.throws(
db.batch.bind(db, 'foo', {}),
/Error: batch\(array\) requires a callback argument/,
'callback-less, 2-arg batch() throws'
)
t.end()
})
test('test batch() with missing `value`', function (t) {
db.batch([{ type: 'put', key: 'foo1' }], function (err) {
t.is(err.message, 'value cannot be `null` or `undefined`', 'correct error message')
t.end()
})
})
test('test batch() with null or undefined `value`', function (t) {
var illegalValues = [null, undefined]
t.plan(illegalValues.length)
illegalValues.forEach(function (value) {
db.batch([{ type: 'put', key: 'foo1', value: value }], function (err) {
t.is(err.message, 'value cannot be `null` or `undefined`', 'correct error message')
})
})
})
test('test batch() with missing `key`', function (t) {
var async = false
db.batch([{ type: 'put', value: 'foo1' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with null or undefined `key`', function (t) {
var illegalKeys = [null, undefined]
t.plan(illegalKeys.length * 3)
illegalKeys.forEach(function (key) {
var async = false
db.batch([{ type: 'put', key: key, value: 'foo1' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
t.ok(async, 'callback is asynchronous')
})
async = true
})
})
test('test batch() with empty `key`', function (t) {
var illegalKeys = [
{ type: 'String', key: '' },
{ type: 'Buffer', key: Buffer.alloc(0) },
{ type: 'Array', key: [] }
]
t.plan(illegalKeys.length * 3)
illegalKeys.forEach(function (item) {
var async = false
db.batch([{ type: 'put', key: item.key, value: 'foo1' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'key cannot be an empty ' + item.type, 'correct error message')
t.ok(async, 'callback is asynchronous')
})
async = true
})
})
test('test batch() with missing `key` and `value`', function (t) {
var async = false
db.batch([{ type: 'put' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with missing `type`', function (t) {
var async = false
db.batch([{ key: 'key', value: 'value' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, "`type` must be 'put' or 'del'", 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with wrong `type`', function (t) {
var async = false
db.batch([{ key: 'key', value: 'value', type: 'foo' }], function (err) {
t.ok(err, 'got error')
t.equal(err.message, "`type` must be 'put' or 'del'", 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with missing array', function (t) {
var async = false
db.batch(function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'batch(array) requires an array argument', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with undefined array', function (t) {
var async = false
db.batch(undefined, function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'batch(array) requires an array argument', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with null array', function (t) {
var async = false
db.batch(null, function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'batch(array) requires an array argument', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test batch() with null options', function (t) {
db.batch([], null, function (err) {
t.error(err)
t.end()
})
})
;[null, undefined, 1, true].forEach(function (element) {
var type = element === null ? 'null' : typeof element
test('test batch() with ' + type + ' element', function (t) {
var async = false
db.batch([element], function (err) {
t.ok(err, 'got error')
t.equal(err.message, 'batch(array) element must be an object and not `null`', 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
})
test('test batch() with empty array', function (t) {
var async = false
db.batch([], function (err) {
t.error(err, 'no error from batch()')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
}
exports.batch = function (test, testCommon) {
test('test simple batch()', function (t) {
db.batch([{ type: 'put', key: 'foo', value: 'bar' }], function (err) {
t.error(err)
db.get('foo', function (err, value) {
t.error(err)
var result
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
} else {
t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer)
result = value.toString()
}
t.equal(result, 'bar')
t.end()
})
})
})
test('test multiple batch()', function (t) {
db.batch([
{ type: 'put', key: 'foobatch1', value: 'bar1' },
{ type: 'put', key: 'foobatch2', value: 'bar2' },
{ type: 'put', key: 'foobatch3', value: 'bar3' },
{ type: 'del', key: 'foobatch2' }
], function (err) {
t.error(err)
var r = 0
var done = function () {
if (++r === 3) { t.end() }
}
db.get('foobatch1', function (err, value) {
t.error(err)
var result
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
} else {
t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer)
result = value.toString()
}
t.equal(result, 'bar1')
done()
})
db.get('foobatch2', function (err, value) {
t.ok(err, 'entry not found')
t.ok(typeof value === 'undefined', 'value is undefined')
t.ok(verifyNotFoundError(err), 'NotFound error')
done()
})
db.get('foobatch3', function (err, value) {
t.error(err)
var result
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
} else {
t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer)
result = value.toString()
}
t.equal(result, 'bar3')
done()
})
})
})
}
exports.atomic = function (test, testCommon) {
test('test multiple batch()', function (t) {
t.plan(4)
var async = false
db.batch([
{ type: 'put', key: 'foobah1', value: 'bar1' },
{ type: 'put', value: 'bar2' },
{ type: 'put', key: 'foobah3', value: 'bar3' }
], function (err) {
t.ok(err, 'should error')
t.ok(async, 'callback is asynchronous')
db.get('foobah1', function (err) {
t.ok(err, 'should not be found')
})
db.get('foobah3', function (err) {
t.ok(err, 'should not be found')
})
})
async = true
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.batch(test, testCommon)
exports.atomic(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/chained-batch-test.js 0000664 0000000 0000000 00000016703 13553424167 0022306 0 ustar 00root root 0000000 0000000 var collectEntries = require('level-concat-iterator')
var db
function collectBatchOps (batch) {
var _put = batch._put
var _del = batch._del
var _operations = []
if (typeof _put !== 'function' || typeof _del !== 'function') {
return batch._operations
}
batch._put = function (key, value) {
_operations.push({ type: 'put', key: key, value: value })
return _put.apply(this, arguments)
}
batch._del = function (key) {
_operations.push({ type: 'del', key: key })
return _del.apply(this, arguments)
}
return _operations
}
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test batch has db reference', function (t) {
t.ok(db.batch().db === db)
t.end()
})
test('test batch#put() with missing `value`', function (t) {
t.plan(1)
try {
db.batch().put('foo1')
} catch (err) {
t.is(err.message, 'value cannot be `null` or `undefined`', 'correct error message')
}
})
test('test batch#put() with missing `key`', function (t) {
try {
db.batch().put(undefined, 'foo1')
} catch (err) {
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#put() with null `key`', function (t) {
try {
db.batch().put(null, 'foo1')
} catch (err) {
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#put() with missing `key` and `value`', function (t) {
try {
db.batch().put()
} catch (err) {
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#put() with null or undefined `value`', function (t) {
var illegalValues = [null, undefined]
t.plan(illegalValues.length)
illegalValues.forEach(function (value) {
try {
db.batch().put('key', value)
} catch (err) {
t.is(err.message, 'value cannot be `null` or `undefined`', 'correct error message')
}
})
})
test('test batch#del() with missing `key`', function (t) {
try {
db.batch().del()
} catch (err) {
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#del() with null or undefined `key`', function (t) {
var illegalKeys = [null, undefined]
t.plan(illegalKeys.length)
illegalKeys.forEach(function (key) {
try {
db.batch().del(key)
} catch (err) {
t.equal(err.message, 'key cannot be `null` or `undefined`', 'correct error message')
}
})
})
test('test batch#clear() doesn\'t throw', function (t) {
db.batch().clear()
t.end()
})
test('test batch#write() with no callback', function (t) {
try {
db.batch().write()
} catch (err) {
t.equal(err.message, 'write() requires a callback argument', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#put() after write()', function (t) {
var batch = db.batch().put('foo', 'bar')
batch.write(function () {})
try {
batch.put('boom', 'bang')
} catch (err) {
t.equal(err.message, 'write() already called on this batch', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#del() after write()', function (t) {
var batch = db.batch().put('foo', 'bar')
batch.write(function () {})
try {
batch.del('foo')
} catch (err) {
t.equal(err.message, 'write() already called on this batch', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#clear() after write()', function (t) {
var batch = db.batch().put('foo', 'bar')
batch.write(function () {})
try {
batch.clear()
} catch (err) {
t.equal(err.message, 'write() already called on this batch', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test batch#write() after write()', function (t) {
var batch = db.batch().put('foo', 'bar')
batch.write(function () {})
try {
batch.write(function () {})
} catch (err) {
t.equal(err.message, 'write() already called on this batch', 'correct error message')
return t.end()
}
t.fail('should have thrown')
t.end()
})
test('test serialize object', function (t) {
var batch = db.batch()
var ops = collectBatchOps(batch)
batch
.put({ foo: 'bar' }, { beep: 'boop' })
.del({ bar: 'baz' })
ops.forEach(function (op) {
t.ok(op.key, '.key is set for .put and .del operations')
if (op.type === 'put') {
t.ok(op.value, '.value is set for .put operation')
}
})
t.end()
})
test('test custom _serialize*', function (t) {
t.plan(4)
var _db = Object.create(db)
var batch = _db.batch()
var ops = collectBatchOps(batch)
_db._serializeKey = function (key) {
t.same(key, { foo: 'bar' })
return 'key1'
}
_db._serializeValue = function (value) {
t.same(value, { beep: 'boop' })
return 'value1'
}
batch.put({ foo: 'bar' }, { beep: 'boop' })
_db._serializeKey = function (key) {
t.same(key, { bar: 'baz' })
return 'key2'
}
batch.del({ bar: 'baz' })
t.deepEqual(ops, [
{ type: 'put', key: 'key1', value: 'value1' },
{ type: 'del', key: 'key2' }
])
})
test('test batch#write() with no operations', function (t) {
var async = false
db.batch().write(function (err) {
t.ifError(err, 'no error from write()')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
}
exports.batch = function (test, testCommon) {
test('test basic batch', function (t) {
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)
db.batch()
.put('1', 'one')
.del('2', 'two')
.put('3', 'three')
.clear()
.put('one', 'I')
.put('two', 'II')
.del('three')
.put('foo', 'bar')
.write(function (err) {
t.error(err)
collectEntries(
db.iterator({ keyAsBuffer: false, valueAsBuffer: false }), function (err, data) {
t.error(err)
t.equal(data.length, 3, 'correct number of entries')
var expected = [
{ key: 'foo', value: 'bar' },
{ key: 'one', value: 'I' },
{ key: 'two', value: 'II' }
]
t.deepEqual(data, expected)
t.end()
}
)
})
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.batch(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/clear-range-test.js 0000664 0000000 0000000 00000012324 13553424167 0022007 0 ustar 00root root 0000000 0000000 var concat = require('level-concat-iterator')
var data = (function () {
var d = []
var i = 0
var k
for (; i < 100; i++) {
k = (i < 10 ? '0' : '') + i
d.push({
key: k,
value: String(Math.random())
})
}
return d
}())
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
}
exports.range = function (test, testCommon) {
function rangeTest (name, opts, expected) {
test('db#clear() with ' + name, function (t) {
prepare(t, function (db) {
db.clear(opts, function (err) {
t.ifError(err, 'no clear error')
verify(t, db, expected)
})
})
})
}
function prepare (t, callback) {
var db = testCommon.factory()
db.open(function (err) {
t.ifError(err, 'no open error')
db.batch(data.map(function (d) {
return {
type: 'put',
key: d.key,
value: d.value
}
}), function (err) {
t.ifError(err, 'no batch error')
callback(db)
})
})
}
function verify (t, db, expected) {
var it = db.iterator({ keyAsBuffer: false, valueAsBuffer: false })
concat(it, function (err, result) {
t.ifError(err, 'no concat error')
t.is(result.length, expected.length, 'correct number of entries')
t.same(result, expected)
db.close(t.end.bind(t))
})
}
function exclude (data, start, end, expectedLength) {
data = data.slice()
var removed = data.splice(start, end - start + 1) // Inclusive
if (expectedLength != null) checkLength(removed, expectedLength)
return data
}
// For sanity checks on test arguments
function checkLength (arr, length) {
if (arr.length !== length) {
throw new RangeError('Expected ' + length + ' elements, got ' + arr.length)
}
return arr
}
rangeTest('full range', {}, [])
// Reversing has no effect without limit
rangeTest('reverse=true', {
reverse: true
}, [])
rangeTest('gte=00', {
gte: '00'
}, [])
rangeTest('gte=50', {
gte: '50'
}, data.slice(0, 50))
rangeTest('lte=50 and reverse=true', {
lte: '50',
reverse: true
}, data.slice(51))
rangeTest('gte=49.5 (midway)', {
gte: '49.5'
}, data.slice(0, 50))
rangeTest('gte=49999 (midway)', {
gte: '49999'
}, data.slice(0, 50))
rangeTest('lte=49.5 (midway) and reverse=true', {
lte: '49.5',
reverse: true
}, data.slice(50))
rangeTest('lt=49.5 (midway) and reverse=true', {
lt: '49.5',
reverse: true
}, data.slice(50))
rangeTest('lt=50 and reverse=true', {
lt: '50',
reverse: true
}, data.slice(50))
rangeTest('lte=50', {
lte: '50'
}, data.slice(51))
rangeTest('lte=50.5 (midway)', {
lte: '50.5'
}, data.slice(51))
rangeTest('lte=50555 (midway)', {
lte: '50555'
}, data.slice(51))
rangeTest('lt=50555 (midway)', {
lt: '50555'
}, data.slice(51))
rangeTest('gte=50.5 (midway) and reverse=true', {
gte: '50.5',
reverse: true
}, data.slice(0, 51))
rangeTest('gt=50.5 (midway) and reverse=true', {
gt: '50.5',
reverse: true
}, data.slice(0, 51))
rangeTest('gt=50 and reverse=true', {
gt: '50',
reverse: true
}, data.slice(0, 51))
// Starting 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
rangeTest('lt=0', {
lt: '0'
}, data)
rangeTest('gte=30 and lte=70', {
gte: '30',
lte: '70'
}, exclude(data, 30, 70))
rangeTest('gt=29 and lt=71', {
gt: '29',
lt: '71'
}, exclude(data, 30, 70))
rangeTest('gte=30 and lte=70 and reverse=true', {
lte: '70',
gte: '30',
reverse: true
}, exclude(data, 30, 70))
rangeTest('gt=29 and lt=71 and reverse=true', {
lt: '71',
gt: '29',
reverse: true
}, exclude(data, 30, 70))
rangeTest('limit=20', {
limit: 20
}, data.slice(20))
rangeTest('limit=20 and gte=20', {
limit: 20,
gte: '20'
}, exclude(data, 20, 39, 20))
rangeTest('limit=20 and reverse=true', {
limit: 20,
reverse: true
}, data.slice(0, -20))
rangeTest('limit=20 and lte=79 and reverse=true', {
limit: 20,
lte: '79',
reverse: true
}, exclude(data, 60, 79, 20))
rangeTest('limit=-1 should clear whole database', {
limit: -1
}, [])
rangeTest('limit=0 should not clear anything', {
limit: 0
}, data)
rangeTest('lte after limit', {
limit: 20,
lte: '50'
}, data.slice(20))
rangeTest('lte before limit', {
limit: 50,
lte: '19'
}, data.slice(20))
rangeTest('gte after database end', {
gte: '9a'
}, data)
rangeTest('gt after database end', {
gt: '9a'
}, data)
rangeTest('lte after database end and reverse=true', {
lte: '9a',
reverse: true
}, [])
rangeTest('lte and gte after database and reverse=true', {
lte: '9b',
gte: '9a',
reverse: true
}, data)
rangeTest('lt and gt after database and reverse=true', {
lt: '9b',
gt: '9a',
reverse: true
}, data)
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.range(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/clear-test.js 0000664 0000000 0000000 00000004257 13553424167 0020723 0 ustar 00root root 0000000 0000000 var concat = require('level-concat-iterator')
var db
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test argument-less clear() throws', function (t) {
t.throws(
db.clear.bind(db),
/Error: clear\(\) requires a callback argument/,
'no-arg clear() throws'
)
t.end()
})
}
exports.clear = function (test, testCommon) {
makeTest('string', ['a', 'b'])
if (testCommon.bufferKeys) {
makeTest('buffer', [Buffer.from('a'), Buffer.from('b')])
makeTest('mixed', [Buffer.from('a'), 'b'])
// These keys would be equal when compared as utf8 strings
makeTest('non-utf8 buffer', [Buffer.from('80', 'hex'), Buffer.from('c0', 'hex')])
}
function makeTest (type, keys) {
test('test simple clear() on ' + type + ' keys', function (t) {
t.plan(8)
var db = testCommon.factory()
var ops = keys.map(function (key) {
return { type: 'put', key: key, value: 'foo' }
})
db.open(function (err) {
t.ifError(err, 'no open error')
db.batch(ops, function (err) {
t.ifError(err, 'no batch error')
concat(db.iterator(), function (err, entries) {
t.ifError(err, 'no concat error')
t.is(entries.length, keys.length, 'has entries')
db.clear(function (err) {
t.ifError(err, 'no clear error')
concat(db.iterator(), function (err, entries) {
t.ifError(err, 'no concat error')
t.is(entries.length, 0, 'has no entries')
db.close(function (err) {
t.ifError(err, 'no close error')
})
})
})
})
})
})
})
}
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.clear(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/close-test.js 0000664 0000000 0000000 00000001551 13553424167 0020734 0 ustar 00root root 0000000 0000000 var db
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.close = function (test, testCommon) {
test('test close()', function (t) {
t.throws(
db.close.bind(db),
/Error: close\(\) requires a callback argument/,
'no-arg close() throws'
)
t.throws(
db.close.bind(db, 'foo'),
/Error: close\(\) requires a callback argument/,
'non-callback close() throws'
)
db.close(function (err) {
t.error(err)
t.end()
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.close(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/common.js 0000664 0000000 0000000 00000001535 13553424167 0020144 0 ustar 00root root 0000000 0000000 function testCommon (options) {
var factory = options.factory
var test = options.test
if (typeof factory !== 'function') {
throw new TypeError('factory must be a function')
}
if (typeof test !== 'function') {
throw new TypeError('test must be a function')
}
return {
test: test,
factory: factory,
// TODO (next major): remove
setUp: options.setUp || noopTest(),
tearDown: options.tearDown || noopTest(),
// TODO (next major): use db.supports instead
bufferKeys: options.bufferKeys !== false,
createIfMissing: options.createIfMissing !== false,
errorIfExists: options.errorIfExists !== false,
snapshots: options.snapshots !== false,
seek: options.seek !== false,
clear: !!options.clear
}
}
function noopTest () {
return function (t) {
t.end()
}
}
module.exports = testCommon
abstract-leveldown-6.2.2/test/del-test.js 0000664 0000000 0000000 00000004431 13553424167 0020373 0 ustar 00root root 0000000 0000000 var db
var verifyNotFoundError = require('./util').verifyNotFoundError
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test argument-less del() throws', function (t) {
t.throws(
db.del.bind(db),
/Error: del\(\) requires a callback argument/,
'no-arg del() throws'
)
t.end()
})
test('test callback-less, 1-arg, del() throws', function (t) {
t.throws(
db.del.bind(db, 'foo'),
/Error: del\(\) requires a callback argument/,
'callback-less, 1-arg del() throws'
)
t.end()
})
test('test callback-less, 3-arg, del() throws', function (t) {
t.throws(
db.del.bind(db, 'foo', {}),
/Error: del\(\) requires a callback argument/,
'callback-less, 2-arg del() throws'
)
t.end()
})
test('test custom _serialize*', function (t) {
t.plan(3)
var db = testCommon.factory()
db._serializeKey = function (data) { return data }
db._del = function (key, options, callback) {
t.deepEqual(key, { foo: 'bar' })
process.nextTick(callback)
}
db.open(function () {
db.del({ foo: 'bar' }, function (err) {
t.error(err)
db.close(t.error.bind(t))
})
})
})
}
exports.del = function (test, testCommon) {
test('test simple del()', function (t) {
db.put('foo', 'bar', function (err) {
t.error(err)
db.del('foo', function (err) {
t.error(err)
db.get('foo', function (err, value) {
t.ok(err, 'entry properly deleted')
t.ok(typeof value === 'undefined', 'value is undefined')
t.ok(verifyNotFoundError(err), 'NotFound error')
t.end()
})
})
})
})
test('test del on non-existent key', function (t) {
db.del('blargh', function (err) {
t.error(err)
t.end()
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.del(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/factory-test.js 0000664 0000000 0000000 00000002021 13553424167 0021267 0 ustar 00root root 0000000 0000000 var 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()
function close () {
db1.close(function (err) {
t.error(err, 'no error while closing db1')
db2.close(function (err) {
t.error(err, 'no error while closing db2')
t.end()
})
})
}
db1.open(function (err) {
t.error(err, 'no error while opening db1')
db2.open(function (err) {
t.error(err, 'no error while opening db2')
db1.put('key', 'value', function (err) {
t.error(err, 'put key in db1')
concat(db2.iterator(), function (err, entries) {
t.error(err, 'got items from db2')
t.same(entries, [], 'db2 should be empty')
close()
})
})
})
})
})
test('tearDown', testCommon.tearDown)
}
abstract-leveldown-6.2.2/test/get-test.js 0000664 0000000 0000000 00000010770 13553424167 0020411 0 ustar 00root root 0000000 0000000 var db
var verifyNotFoundError = require('./util').verifyNotFoundError
var isTypedArray = require('./util').isTypedArray
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test argument-less get() throws', function (t) {
t.throws(
db.get.bind(db),
/Error: get\(\) requires a callback argument/,
'no-arg get() throws'
)
t.end()
})
test('test callback-less, 1-arg, get() throws', function (t) {
t.throws(
db.get.bind(db, 'foo'),
/Error: get\(\) requires a callback argument/,
'callback-less, 1-arg get() throws'
)
t.end()
})
test('test callback-less, 3-arg, get() throws', function (t) {
t.throws(
db.get.bind(db, 'foo', {}),
/Error: get\(\) requires a callback argument/,
'callback-less, 2-arg get() throws'
)
t.end()
})
test('test custom _serialize*', function (t) {
t.plan(3)
var db = testCommon.factory()
db._serializeKey = function (data) { return data }
db._get = function (key, options, callback) {
t.deepEqual(key, { foo: 'bar' })
process.nextTick(callback)
}
db.open(function () {
db.get({ foo: 'bar' }, function (err) {
t.error(err)
db.close(t.error.bind(t))
})
})
})
}
exports.get = function (test, testCommon) {
test('test simple get()', function (t) {
db.put('foo', 'bar', function (err) {
t.error(err)
db.get('foo', function (err, value) {
t.error(err)
t.ok(typeof value !== 'string', 'should not be string by default')
var result
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
} else {
t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer)
try {
result = value.toString()
} catch (e) {
t.error(e, 'should not throw when converting value to a string')
}
}
t.equal(result, 'bar')
db.get('foo', {}, function (err, value) { // same but with {}
t.error(err)
t.ok(typeof value !== 'string', 'should not be string by default')
var result
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
} else {
t.ok(typeof Buffer !== 'undefined' && value instanceof Buffer)
try {
result = value.toString()
} catch (e) {
t.error(e, 'should not throw when converting value to a string')
}
}
t.equal(result, 'bar')
db.get('foo', { asBuffer: false }, function (err, value) {
t.error(err)
t.ok(typeof value === 'string', 'should be string if not buffer')
t.equal(value, 'bar')
t.end()
})
})
})
})
})
test('test simultaniously get()', function (t) {
db.put('hello', 'world', function (err) {
t.error(err)
var r = 0
var done = function () {
if (++r === 20) { t.end() }
}
var i = 0
var j = 0
for (; i < 10; ++i) {
db.get('hello', function (err, value) {
t.error(err)
t.equal(value.toString(), 'world')
done()
})
}
for (; j < 10; ++j) {
db.get('not found', function (err, value) {
t.ok(err, 'should error')
t.ok(verifyNotFoundError(err), 'should have correct error message')
t.ok(typeof value === 'undefined', 'value is undefined')
done()
})
}
})
})
test('test get() not found error is asynchronous', function (t) {
t.plan(5)
db.put('hello', 'world', function (err) {
t.error(err)
var async = false
db.get('not found', function (err, value) {
t.ok(err, 'should error')
t.ok(verifyNotFoundError(err), 'should have correct error message')
t.ok(typeof value === 'undefined', 'value is undefined')
t.ok(async, 'callback is asynchronous')
})
async = true
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.get(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/index.js 0000664 0000000 0000000 00000002624 13553424167 0017763 0 ustar 00root root 0000000 0000000 var common = require('./common')
function suite (options) {
var testCommon = common(options)
var test = testCommon.test
require('./factory-test')(test, testCommon)
require('./manifest-test')(test, testCommon)
require('./leveldown-test')(test, testCommon)
require('./open-test').all(test, testCommon)
require('./close-test').all(test, testCommon)
if (testCommon.createIfMissing) {
require('./open-create-if-missing-test').all(test, testCommon)
}
if (testCommon.errorIfExists) {
require('./open-error-if-exists-test').all(test, testCommon)
}
require('./put-test').all(test, testCommon)
require('./get-test').all(test, testCommon)
require('./del-test').all(test, testCommon)
require('./put-get-del-test').all(test, testCommon)
require('./batch-test').all(test, testCommon)
require('./chained-batch-test').all(test, testCommon)
require('./iterator-test').all(test, testCommon)
require('./iterator-range-test').all(test, testCommon)
if (testCommon.seek) {
require('./iterator-seek-test').all(test, testCommon)
}
if (testCommon.snapshots) {
require('./iterator-snapshot-test').all(test, testCommon)
} else {
require('./iterator-no-snapshot-test').all(test, testCommon)
}
if (testCommon.clear) {
require('./clear-test').all(test, testCommon)
require('./clear-range-test').all(test, testCommon)
}
}
suite.common = common
module.exports = suite
abstract-leveldown-6.2.2/test/iterator-no-snapshot-test.js 0000664 0000000 0000000 00000003722 13553424167 0023731 0 ustar 00root root 0000000 0000000 var collectEntries = require('level-concat-iterator')
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
}
exports.noSnapshot = function (test, testCommon) {
function make (run) {
return function (t) {
var db = testCommon.factory()
var operations = [
{ type: 'put', key: 'a', value: 'a' },
{ type: 'put', key: 'b', value: 'b' },
{ type: 'put', key: 'c', value: 'c' }
]
db.open(function (err) {
t.ifError(err, 'no open error')
db.batch(operations, function (err) {
t.ifError(err, 'no batch error')
// 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 })
run(db, function (err) {
t.ifError(err, 'no run error')
verify(t, it, db)
})
})
})
}
}
function verify (t, it, db) {
collectEntries(it, function (err, entries) {
t.ifError(err, 'no iterator error')
var kv = entries.map(function (entry) {
return entry.key.toString() + entry.value.toString()
})
if (kv.length === 3) {
t.same(kv, ['aa', 'bb', 'cc'], 'maybe supports snapshots')
} else {
t.same(kv, ['aa', 'cc'], 'ignores keys that have been deleted in the mean time')
}
db.close(t.end.bind(t))
})
}
test('delete key after creating iterator', make(function (db, done) {
db.del('b', done)
}))
test('batch delete key after creating iterator', make(function (db, done) {
db.batch([{ type: 'del', key: 'b' }], done)
}))
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.noSnapshot(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/iterator-range-test.js 0000664 0000000 0000000 00000022676 13553424167 0022565 0 ustar 00root root 0000000 0000000 var collectEntries = require('level-concat-iterator')
var xtend = require('xtend')
var db
var data = (function () {
var d = []
var i = 0
var k
for (; i < 100; i++) {
k = (i < 10 ? '0' : '') + i
d.push({
key: k,
value: String(Math.random())
})
}
return d
}())
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(function () {
db.batch(data.map(function (d) {
return {
type: 'put',
key: d.key,
value: d.value
}
}), t.end.bind(t))
})
})
}
exports.range = function (test, testCommon) {
function rangeTest (name, opts, expected) {
opts.keyAsBuffer = false
opts.valueAsBuffer = false
test(name, function (t) {
collectEntries(db.iterator(opts), function (err, result) {
t.error(err)
t.is(result.length, expected.length, 'correct number of entries')
t.same(result, expected)
t.end()
})
})
// 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
}
rangeTest(
name + ' (flipped)',
reverseOpts,
expected.slice().reverse()
)
}
}
rangeTest('test full data collection', {}, data)
rangeTest('test iterator with reverse=true', {
reverse: true
}, data.slice().reverse())
rangeTest('test iterator with gte=00', {
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
}, data.slice().reverse().slice(50))
rangeTest('test iterator with lt=49.5 (midway) and reverse=true', {
lt: '49.5',
reverse: true
}, data.slice().reverse().slice(50))
rangeTest('test iterator with lt=50 and reverse=true', {
lt: '50',
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))
rangeTest('test iterator with lt=50555 (midway)', {
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
}, data.slice().reverse().slice(0, 49))
rangeTest('test iterator with gt=50.5 (midway) and reverse=true', {
gt: '50.5',
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
rangeTest('test iterator with lte=0', {
lte: '0'
}, [])
// end='0', starting 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'
}, data.slice(30, 71))
rangeTest('test iterator with gt=29 and lt=71', {
gt: '29',
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',
reverse: true
}, data.slice().reverse().slice(29, 70))
rangeTest('test iterator with gt=29 and lt=71 and reverse=true', {
lt: '71',
gt: '29',
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))
rangeTest('test iterator with limit=20 and gte=20', {
limit: 20,
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
}, data.slice().reverse().slice(0, 20))
rangeTest('test iterator with limit=20 and lte=79 and reverse=true', {
limit: 20,
lte: '79',
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
}, data)
rangeTest('test iterator with limit=0 should not iterate over anything', {
limit: 0
}, [])
rangeTest('test iterator with lte after limit', {
limit: 20,
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'
}, [])
rangeTest('test iterator with gt after database end', {
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))
rangeTest('test iterator with lte at database end', {
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))
rangeTest('test iterator with lte before database end', {
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',
reverse: true
}, [])
rangeTest('test iterator with lt and gt after database and reverse=true', {
lt: '9b',
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) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.range(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/iterator-seek-test.js 0000664 0000000 0000000 00000017636 13553424167 0022420 0 ustar 00root root 0000000 0000000 exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.sequence(test, testCommon)
exports.seek(test, testCommon)
exports.tearDown(test, testCommon)
}
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
}
exports.sequence = function (test, testCommon) {
function make (name, testFn) {
test(name, function (t) {
var db = testCommon.factory()
var done = function (err) {
t.error(err, 'no error from done()')
db.close(function (err) {
t.error(err, 'no error from close()')
t.end()
})
}
db.open(function (err) {
t.error(err, 'no error from open()')
testFn(db, t, done)
})
})
}
make('iterator#seek() throws if next() has not completed', function (db, t, done) {
var ite = db.iterator()
var error
var async = false
ite.next(function (err, key, value) {
t.error(err, 'no error from next()')
t.ok(async, 'next is asynchronous')
ite.end(done)
})
async = true
try {
ite.seek('two')
} catch (err) {
error = err.message
}
t.is(error, 'cannot call seek() before next() has completed', 'got error')
})
make('iterator#seek() throws after end()', function (db, t, done) {
var ite = db.iterator()
// TODO: why call next? Can't we end immediately?
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()
})
})
})
}
exports.seek = function (test, testCommon) {
function make (name, testFn) {
test(name, function (t) {
var db = testCommon.factory()
var done = function (err) {
t.error(err, 'no error from done()')
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)
})
})
})
}
make('iterator#seek() to string target', 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)
})
})
})
if (testCommon.bufferKeys) {
make('iterator#seek() to buffer target', 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('iterator#seek() on reverse iterator', 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#seek() to out of range target', 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('iterator#seek() on reverse iterator to out of range target', 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)
})
})
test('iterator#seek() respects range', function (t) {
var db = testCommon.factory()
db.open(function (err) {
t.error(err, 'no error from open()')
// Can't use Array.fill() because IE
var ops = []
for (var 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
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 json = JSON.stringify(range)
var msg = 'seek(' + target + ') on ' + json + ' yields ' + 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 done () {
db.close(function (err) {
t.error(err, 'no error from close()')
t.end()
})
}
})
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
abstract-leveldown-6.2.2/test/iterator-snapshot-test.js 0000664 0000000 0000000 00000004641 13553424167 0023320 0 ustar 00root root 0000000 0000000 exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
}
exports.snapshot = function (test, testCommon) {
function make (run) {
return function (t) {
var db = testCommon.factory()
db.open(function (err) {
t.ifError(err, 'no open error')
db.put('z', 'from snapshot', function (err) {
t.ifError(err, 'no put error')
// 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 })
run(t, db, it, function end (err) {
t.ifError(err, 'no run error')
it.end(function (err) {
t.ifError(err, 'no iterator end error')
db.close(t.end.bind(t))
})
})
})
})
}
}
test('delete key after snapshotting', make(function (t, db, it, end) {
db.del('z', function (err) {
t.ifError(err, 'no del error')
it.next(function (err, key, value) {
t.ifError(err, 'no next error')
t.ok(key, 'got a key')
t.is(key.toString(), 'z', 'correct key')
t.is(value.toString(), 'from snapshot', 'correct value')
end()
})
})
}))
test('overwrite key after snapshotting', make(function (t, db, it, end) {
db.put('z', 'not from snapshot', function (err) {
t.ifError(err, 'no put error')
it.next(function (err, key, value) {
t.ifError(err, 'no next error')
t.ok(key, 'got a key')
t.is(key.toString(), 'z', 'correct key')
t.is(value.toString(), 'from snapshot', 'correct value')
end()
})
})
}))
test('add key after snapshotting that sorts first', make(function (t, db, it, end) {
db.put('a', 'not from snapshot', function (err) {
t.ifError(err, 'no put error')
it.next(function (err, key, value) {
t.ifError(err, 'no next error')
t.ok(key, 'got a key')
t.is(key.toString(), 'z', 'correct key')
t.is(value.toString(), 'from snapshot', 'correct value')
end()
})
})
}))
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.snapshot(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/iterator-test.js 0000664 0000000 0000000 00000011173 13553424167 0021461 0 ustar 00root root 0000000 0000000 var db
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test iterator has db reference', function (t) {
var iterator = db.iterator()
t.ok(iterator.db === db)
iterator.end(t.end.bind(t))
})
test('test argument-less iterator#next() throws', function (t) {
var iterator = db.iterator()
t.throws(
iterator.next.bind(iterator),
/Error: next\(\) requires a callback argument/,
'no-arg iterator#next() throws'
)
iterator.end(t.end.bind(t))
})
test('test argument-less iterator#end() after next() throws', function (t) {
var iterator = db.iterator()
iterator.next(function () {
t.throws(
iterator.end.bind(iterator),
/Error: end\(\) requires a callback argument/,
'no-arg iterator#end() throws'
)
iterator.end(t.end.bind(t))
})
})
test('test argument-less iterator#end() throws', function (t) {
var iterator = db.iterator()
t.throws(
iterator.end.bind(iterator),
/Error: end\(\) requires a callback argument/,
'no-arg iterator#end() throws'
)
iterator.end(t.end.bind(t))
})
test('test iterator#next returns this', function (t) {
var iterator = db.iterator()
var self = iterator.next(function () {})
t.ok(iterator === self)
iterator.end(t.end.bind(t))
})
}
exports.sequence = function (test, testCommon) {
test('test twice iterator#end() callback with error', function (t) {
var iterator = db.iterator()
iterator.end(function (err) {
t.error(err)
var async = false
iterator.end(function (err2) {
t.ok(err2, 'returned error')
t.is(err2.name, 'Error', 'correct error')
t.is(err2.message, 'end() already called on iterator')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
})
test('test iterator#next after iterator#end() callback with error', function (t) {
var iterator = db.iterator()
iterator.end(function (err) {
t.error(err)
var async = false
iterator.next(function (err2) {
t.ok(err2, 'returned error')
t.is(err2.name, 'Error', 'correct error')
t.is(err2.message, 'cannot call next() after end()', 'correct message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
})
test('test twice iterator#next() throws', function (t) {
var iterator = db.iterator()
iterator.next(function (err) {
t.error(err)
iterator.end(function (err) {
t.error(err)
t.end()
})
})
var async = false
iterator.next(function (err) {
t.ok(err, 'returned error')
t.is(err.name, 'Error', 'correct error')
t.is(err.message, 'cannot call next() before previous next() has completed')
t.ok(async, 'callback is asynchronous')
})
async = true
})
}
exports.iterator = function (test, testCommon) {
test('test simple iterator()', function (t) {
var data = [
{ type: 'put', key: 'foobatch1', value: 'bar1' },
{ type: 'put', key: 'foobatch2', value: 'bar2' },
{ type: 'put', key: 'foobatch3', value: 'bar3' }
]
var idx = 0
db.batch(data, function (err) {
t.error(err)
var iterator = db.iterator()
var fn = function (err, key, value) {
t.error(err)
if (key && value) {
t.ok(Buffer.isBuffer(key), 'key argument is a Buffer')
t.ok(Buffer.isBuffer(value), 'value argument is a Buffer')
t.is(key.toString(), data[idx].key, 'correct key')
t.is(value.toString(), data[idx].value, 'correct value')
process.nextTick(next)
idx++
} else { // end
t.ok(typeof err === 'undefined', 'err argument is undefined')
t.ok(typeof key === 'undefined', 'key argument is undefined')
t.ok(typeof value === 'undefined', 'value argument is undefined')
t.is(idx, data.length, 'correct number of entries')
iterator.end(function () {
t.end()
})
}
}
var next = function () {
iterator.next(fn)
}
next()
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.sequence(test, testCommon)
exports.iterator(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/leveldown-test.js 0000664 0000000 0000000 00000000534 13553424167 0021626 0 ustar 00root root 0000000 0000000 module.exports = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('test database open method exists', function (t) {
var db = testCommon.factory()
t.ok(db, 'database object returned')
t.ok(typeof db.open === 'function', 'open() function exists')
t.end()
})
test('tearDown', testCommon.tearDown)
}
abstract-leveldown-6.2.2/test/manifest-test.js 0000664 0000000 0000000 00000001063 13553424167 0021433 0 ustar 00root root 0000000 0000000 var suite = require('level-supports/test')
module.exports = function (test, testCommon) {
test('setUp common', testCommon.setUp)
suite(test, testCommon)
test('manifest has status', function (t) {
var db = testCommon.factory()
t.is(db.supports.status, true)
// The semantics of not opening or closing a new db are unclear
// atm, so let's open it before closing, like every other test.
db.open(function (err) {
t.ifError(err, 'no open error')
db.close(t.end.bind(t))
})
})
test('tearDown', testCommon.tearDown)
}
abstract-leveldown-6.2.2/test/open-create-if-missing-test.js 0000664 0000000 0000000 00000001404 13553424167 0024071 0 ustar 00root root 0000000 0000000 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
db.open({ createIfMissing: false }, function (err) {
t.ok(err, 'error')
t.ok(/does not exist/.test(err.message), 'error is about dir not existing')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.createIfMissing(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/open-error-if-exists-test.js 0000664 0000000 0000000 00000001645 13553424167 0023634 0 ustar 00root root 0000000 0000000 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()
db.open({}, function (err) {
t.error(err)
db.close(function (err) {
t.error(err)
var async = false
db.open({ createIfMissing: false, errorIfExists: true }, function (err) {
t.ok(err, 'error')
t.ok(/exists/.test(err.message), 'error is about already existing')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.errorIfExists(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/open-test.js 0000664 0000000 0000000 00000003463 13553424167 0020574 0 ustar 00root root 0000000 0000000 exports.setUp = function (test, testCommon) {
test('setUp', testCommon.setUp)
}
exports.args = function (test, testCommon) {
test('test database open no-arg throws', function (t) {
var db = testCommon.factory()
t.throws(
db.open.bind(db),
/Error: open\(\) requires a callback argument/,
'no-arg open() throws'
)
t.end()
})
test('test callback-less, 1-arg, open() throws', function (t) {
var db = testCommon.factory()
t.throws(
db.open.bind(db, {}),
/Error: open\(\) requires a callback argument/,
'callback-less, 1-arg open() throws'
)
t.end()
})
}
exports.open = function (test, testCommon) {
test('test database open, no options', function (t) {
var db = testCommon.factory()
// default createIfMissing=true, errorIfExists=false
db.open(function (err) {
t.error(err)
db.close(function () {
t.end()
})
})
})
test('test database open, options and callback', function (t) {
var db = testCommon.factory()
// default createIfMissing=true, errorIfExists=false
db.open({}, function (err) {
t.error(err)
db.close(function () {
t.end()
})
})
})
test('test database open, close and open', function (t) {
var db = testCommon.factory()
db.open(function (err) {
t.error(err)
db.close(function (err) {
t.error(err)
db.open(function (err) {
t.error(err)
db.close(function () {
t.end()
})
})
})
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', testCommon.tearDown)
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.open(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/put-get-del-test.js 0000664 0000000 0000000 00000013101 13553424167 0021750 0 ustar 00root root 0000000 0000000 'use strict'
var db
var verifyNotFoundError = require('./util').verifyNotFoundError
var testBuffer = Buffer.from('testbuffer')
function makeGetDelErrorTests (test, type, key, expectedError) {
test('test get() with ' + type + ' causes error', function (t) {
var async = false
db.get(key, function (err) {
t.ok(err, 'has error')
t.ok(err instanceof Error)
t.ok(err.message.match(expectedError), 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test del() with ' + type + ' causes error', function (t) {
var async = false
db.del(key, function (err) {
t.ok(err, 'has error')
t.ok(err instanceof Error)
t.ok(err.message.match(expectedError), 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
}
function makePutErrorTest (test, type, key, value, expectedError) {
test('test put() with ' + type + ' causes error', function (t) {
var async = false
db.put(key, value, function (err) {
t.ok(err, 'has error')
t.ok(err instanceof Error)
t.ok(err.message.match(expectedError), 'correct error message')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
}
function makePutGetDelSuccessfulTest (test, type, key, value, expectedResult) {
var hasExpectedResult = arguments.length === 5
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 + '`')
t.ok(Buffer.isBuffer(_value), 'is a Buffer')
var result = _value
if (hasExpectedResult) {
t.equal(result.toString(), expectedResult)
} else {
if (result != null) { result = _value.toString() }
if (value != null) { value = value.toString() }
t.equals(result, value)
}
db.del(key, function (err) {
t.error(err, 'no error, deleted key/value for `' + type + '`')
var async = false
db.get(key, function (err, value) {
t.ok(err, 'entry properly deleted')
t.ok(verifyNotFoundError(err), 'should have correct error message')
t.equal(typeof value, 'undefined', 'value is undefined')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
})
})
})
}
function makeErrorKeyTest (test, type, key, expectedError) {
makeGetDelErrorTests(test, type, key, expectedError)
makePutErrorTest(test, type, key, 'foo', expectedError)
}
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.errorKeys = function (test, testCommon) {
makeErrorKeyTest(test, 'null key', null, /key cannot be `null` or `undefined`/)
makeErrorKeyTest(test, 'undefined key', undefined, /key cannot be `null` or `undefined`/)
makeErrorKeyTest(test, 'empty String key', '', /key cannot be an empty String/)
makeErrorKeyTest(test, 'empty Buffer key', Buffer.alloc(0), /key cannot be an empty \w*Buffer/)
makeErrorKeyTest(test, 'empty Array key', [], /key cannot be an empty Array/)
}
exports.errorValues = function (test, testCommon) {
makePutErrorTest(test, 'null value', 'key', null, /value cannot be `null` or `undefined`/)
makePutErrorTest(test, 'undefined value', 'key', undefined, /value cannot be `null` or `undefined`/)
}
exports.nonErrorKeys = function (test, testCommon) {
// valid falsey keys
makePutGetDelSuccessfulTest(test, '`0` key', 0, 'foo 0')
// standard String key
makePutGetDelSuccessfulTest(
test
, 'long String key'
, 'some long string that I\'m using as a key for this unit test, cross your fingers human, we\'re going in!'
, 'foo'
)
if (testCommon.bufferKeys) {
makePutGetDelSuccessfulTest(test, 'Buffer key', testBuffer, 'foo')
}
// non-empty Array as a value
makePutGetDelSuccessfulTest(test, 'Array value', 'foo', [1, 2, 3, 4])
}
exports.nonErrorValues = function (test, testCommon) {
// valid falsey values
makePutGetDelSuccessfulTest(test, '`false` value', 'foo false', false)
makePutGetDelSuccessfulTest(test, '`0` value', 'foo 0', 0)
makePutGetDelSuccessfulTest(test, '`NaN` value', 'foo NaN', NaN)
// all of the following result in an empty-string value:
makePutGetDelSuccessfulTest(test, 'empty String value', 'foo', '', '')
makePutGetDelSuccessfulTest(test, 'empty Buffer value', 'foo', Buffer.alloc(0), '')
// note that an implementation may return the value as an array
makePutGetDelSuccessfulTest(test, 'empty Array value', 'foo', [], '')
// standard String value
makePutGetDelSuccessfulTest(
test
, 'long String value'
, 'foo'
, 'some long string that I\'m using as a key for this unit test, cross your fingers human, we\'re going in!'
)
// standard Buffer value
makePutGetDelSuccessfulTest(test, 'Buffer value', 'foo', testBuffer)
// non-empty Array as a key
makePutGetDelSuccessfulTest(test, 'Array key', [1, 2, 3, 4], 'foo')
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.errorKeys(test, testCommon)
exports.errorValues(test, testCommon)
exports.nonErrorKeys(test, testCommon)
exports.nonErrorValues(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/put-test.js 0000664 0000000 0000000 00000005321 13553424167 0020436 0 ustar 00root root 0000000 0000000 var db
var isTypedArray = require('./util').isTypedArray
exports.setUp = function (test, testCommon) {
test('setUp common', testCommon.setUp)
test('setUp db', function (t) {
db = testCommon.factory()
db.open(t.end.bind(t))
})
}
exports.args = function (test, testCommon) {
test('test argument-less put() throws', function (t) {
t.throws(
db.put.bind(db),
/Error: put\(\) requires a callback argument/,
'no-arg put() throws'
)
t.end()
})
test('test callback-less, 1-arg, put() throws', function (t) {
t.throws(
db.put.bind(db, 'foo'),
/Error: put\(\) requires a callback argument/,
'callback-less, 1-arg put() throws'
)
t.end()
})
test('test callback-less, 2-arg, put() throws', function (t) {
t.throws(
db.put.bind(db, 'foo', 'bar'),
/Error: put\(\) requires a callback argument/,
'callback-less, 2-arg put() throws'
)
t.end()
})
test('test callback-less, 3-arg, put() throws', function (t) {
t.throws(
db.put.bind(db, 'foo', 'bar', {}),
/Error: put\(\) requires a callback argument/,
'callback-less, 3-arg put() throws'
)
t.end()
})
test('test _serialize object', function (t) {
t.plan(3)
var db = testCommon.factory()
db._put = function (key, value, opts, callback) {
t.ok(key)
t.ok(value)
process.nextTick(callback)
}
db.put({}, {}, function (err, val) {
t.error(err)
})
})
test('test custom _serialize*', function (t) {
t.plan(4)
var 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)
}
db.open(function () {
db.put({ foo: 'bar' }, { beep: 'boop' }, function (err) {
t.error(err)
db.close(t.error.bind(t))
})
})
})
}
exports.put = function (test, testCommon) {
test('test simple put()', function (t) {
db.put('foo', 'bar', function (err) {
t.error(err)
db.get('foo', function (err, value) {
t.error(err)
var result = value.toString()
if (isTypedArray(value)) {
result = String.fromCharCode.apply(null, new Uint16Array(value))
}
t.equal(result, 'bar')
t.end()
})
})
})
}
exports.tearDown = function (test, testCommon) {
test('tearDown', function (t) {
db.close(testCommon.tearDown.bind(null, t))
})
}
exports.all = function (test, testCommon) {
exports.setUp(test, testCommon)
exports.args(test, testCommon)
exports.put(test, testCommon)
exports.tearDown(test, testCommon)
}
abstract-leveldown-6.2.2/test/self.js 0000664 0000000 0000000 00000075426 13553424167 0017617 0 ustar 00root root 0000000 0000000 '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')({
test: test,
clear: true,
factory: function () {
return new AbstractLevelDOWN()
}
})
var rangeOptions = ['gt', 'gte', 'lt', 'lte']
var legacyRangeOptions = ['start', 'end']
// Test the suite itself as well as the default implementation,
// excluding noop operations that can't pass the test suite.
require('./leveldown-test')(test, testCommon)
require('./manifest-test')(test, testCommon)
require('./open-test').all(test, testCommon)
require('./open-create-if-missing-test').setUp(test, testCommon)
require('./open-create-if-missing-test').tearDown(test, testCommon)
require('./open-error-if-exists-test').setUp(test, testCommon)
require('./open-error-if-exists-test').tearDown(test, testCommon)
require('./del-test').setUp(test, testCommon)
require('./del-test').args(test, testCommon)
require('./get-test').setUp(test, testCommon)
require('./get-test').args(test, testCommon)
require('./put-test').setUp(test, testCommon)
require('./put-test').args(test, testCommon)
require('./put-get-del-test').setUp(test, testCommon)
require('./put-get-del-test').errorKeys(test, testCommon)
require('./put-get-del-test').tearDown(test, testCommon)
require('./batch-test').setUp(test, testCommon)
require('./batch-test').args(test, testCommon)
require('./chained-batch-test').setUp(test, testCommon)
require('./chained-batch-test').args(test, testCommon)
require('./chained-batch-test').tearDown(test, testCommon)
require('./close-test').all(test, testCommon)
require('./iterator-test').setUp(test, testCommon)
require('./iterator-test').args(test, testCommon)
require('./iterator-test').sequence(test, testCommon)
require('./iterator-test').tearDown(test, testCommon)
require('./iterator-range-test').setUp(test, testCommon)
require('./iterator-range-test').tearDown(test, testCommon)
require('./iterator-snapshot-test').setUp(test, testCommon)
require('./iterator-snapshot-test').tearDown(test, testCommon)
require('./iterator-no-snapshot-test').setUp(test, testCommon)
require('./iterator-no-snapshot-test').tearDown(test, testCommon)
require('./iterator-seek-test').setUp(test, testCommon)
require('./iterator-seek-test').sequence(test, testCommon)
require('./iterator-seek-test').tearDown(test, testCommon)
require('./clear-test').setUp(test, testCommon)
require('./clear-test').args(test, testCommon)
require('./clear-test').tearDown(test, testCommon)
require('./clear-range-test').setUp(test, testCommon)
require('./clear-range-test').tearDown(test, testCommon)
function implement (ctor, methods) {
function Test () {
ctor.apply(this, arguments)
}
inherits(Test, ctor)
for (var k in methods) {
Test.prototype[k] = methods[k]
}
return Test
}
/**
* Extensibility
*/
test('test core extensibility', function (t) {
var Test = implement(AbstractLevelDOWN)
var 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()
;['', {}, null, undefined, Buffer.alloc(0)].forEach(function (v) {
t.ok(test._serializeKey(v) === v, '_serializeKey is an identity function')
t.ok(test._serializeValue(v) === v, '_serializeValue is an identity function')
})
t.end()
})
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')
test.open(expectedCb)
t.equal(spy.callCount, 1, 'got _open() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _open() was correct')
t.equal(spy.getCall(0).args.length, 2, 'got two arguments')
t.deepEqual(spy.getCall(0).args[0], expectedOptions, 'got default options argument')
test.open({ options: 1 }, expectedCb)
expectedOptions.options = 1
t.equal(spy.callCount, 2, 'got _open() call')
t.equal(spy.getCall(1).thisValue, test, '`this` on _open() was correct')
t.equal(spy.getCall(1).args.length, 2, 'got two arguments')
t.deepEqual(spy.getCall(1).args[0], expectedOptions, 'got expected options argument')
t.end()
})
test('test close() extensibility', function (t) {
var spy = sinon.spy()
var expectedCb = function () {}
var Test = implement(AbstractLevelDOWN, { _close: spy })
var test = new Test('foobar')
test.close(expectedCb)
t.equal(spy.callCount, 1, 'got _close() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _close() was correct')
t.equal(spy.getCall(0).args.length, 1, 'got one arguments')
t.end()
})
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')
test.get(expectedKey, expectedCb)
t.equal(spy.callCount, 1, 'got _get() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _get() was correct')
t.equal(spy.getCall(0).args.length, 3, 'got three arguments')
t.equal(spy.getCall(0).args[0], expectedKey, 'got expected key argument')
t.deepEqual(spy.getCall(0).args[1], expectedOptions, 'got default options argument')
t.equal(spy.getCall(0).args[2], expectedCb, 'got expected cb argument')
test.get(expectedKey, { options: 1 }, expectedCb)
expectedOptions.options = 1
t.equal(spy.callCount, 2, 'got _get() call')
t.equal(spy.getCall(1).thisValue, test, '`this` on _get() was correct')
t.equal(spy.getCall(1).args.length, 3, 'got three arguments')
t.equal(spy.getCall(1).args[0], expectedKey, 'got expected key argument')
t.deepEqual(spy.getCall(1).args[1], expectedOptions, 'got expected options argument')
t.equal(spy.getCall(1).args[2], expectedCb, 'got expected cb argument')
t.end()
})
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')
test.del(expectedKey, expectedCb)
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, 3, 'got three arguments')
t.equal(spy.getCall(0).args[0], expectedKey, 'got expected key argument')
t.deepEqual(spy.getCall(0).args[1], {}, 'got blank options argument')
t.equal(spy.getCall(0).args[2], expectedCb, 'got expected cb argument')
test.del(expectedKey, expectedOptions, expectedCb)
t.equal(spy.callCount, 2, 'got _del() call')
t.equal(spy.getCall(1).thisValue, test, '`this` on _del() was correct')
t.equal(spy.getCall(1).args.length, 3, 'got three arguments')
t.equal(spy.getCall(1).args[0], expectedKey, 'got expected key argument')
t.deepEqual(spy.getCall(1).args[1], expectedOptions, 'got expected options argument')
t.equal(spy.getCall(1).args[2], expectedCb, 'got expected cb argument')
t.end()
})
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')
test.put(expectedKey, expectedValue, expectedCb)
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, 4, 'got four 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.deepEqual(spy.getCall(0).args[2], {}, 'got blank options argument')
t.equal(spy.getCall(0).args[3], expectedCb, 'got expected cb argument')
test.put(expectedKey, expectedValue, expectedOptions, expectedCb)
t.equal(spy.callCount, 2, 'got _put() call')
t.equal(spy.getCall(1).thisValue, test, '`this` on _put() was correct')
t.equal(spy.getCall(1).args.length, 4, 'got four arguments')
t.equal(spy.getCall(1).args[0], expectedKey, 'got expected key argument')
t.equal(spy.getCall(1).args[1], expectedValue, 'got expected value argument')
t.deepEqual(spy.getCall(1).args[2], expectedOptions, 'got blank options argument')
t.equal(spy.getCall(1).args[3], expectedCb, 'got expected cb argument')
t.end()
})
test('test batch([]) (array-form) extensibility', function (t) {
var spy = sinon.spy()
var expectedCb = function () {}
var expectedOptions = { options: 1 }
var expectedArray = [
{ type: 'put', key: '1', value: '1' },
{ type: 'del', key: '2' }
]
var Test = implement(AbstractLevelDOWN, { _batch: spy })
var test = new Test('foobar')
test.batch(expectedArray, expectedCb)
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _batch() was correct')
t.equal(spy.getCall(0).args.length, 3, 'got three arguments')
t.deepEqual(spy.getCall(0).args[0], expectedArray, 'got expected array argument')
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(expectedArray, 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.deepEqual(spy.getCall(1).args[0], expectedArray, 'got expected array argument')
t.deepEqual(spy.getCall(1).args[1], expectedOptions, 'got expected options argument')
t.equal(spy.getCall(1).args[2], expectedCb, 'got expected callback argument')
test.batch(expectedArray, null, expectedCb)
t.equal(spy.callCount, 3, 'got _batch() call')
t.equal(spy.getCall(2).thisValue, test, '`this` on _batch() was correct')
t.equal(spy.getCall(2).args.length, 3, 'got three arguments')
t.deepEqual(spy.getCall(2).args[0], expectedArray, 'got expected array argument')
t.ok(spy.getCall(2).args[1], 'options should not be null')
t.equal(spy.getCall(2).args[2], expectedCb, 'got expected callback argument')
t.end()
})
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
test.batch([], function (err) {
t.ifError(err, 'no error')
t.ok(async, 'callback is asynchronous')
// Assert that asynchronicity is provided by batch() rather than _batch()
t.is(spy.callCount, 0, '_batch() call was bypassed')
t.end()
})
async = true
})
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')
test.batch().put('foo', 'bar').del('bang').write(expectedCb)
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _batch() was correct')
t.equal(spy.getCall(0).args.length, 3, 'got three arguments')
t.equal(spy.getCall(0).args[0].length, 2, 'got expected array argument')
t.deepEqual(spy.getCall(0).args[0][0], { type: 'put', key: 'foo', value: 'bar' }, 'got expected array argument[0]')
t.deepEqual(spy.getCall(0).args[0][1], { type: 'del', key: 'bang' }, 'got expected array argument[1]')
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)
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[1], expectedOptions, 'got expected options argument')
t.equal(spy.getCall(1).args[2], expectedCb, 'got expected callback argument')
t.end()
})
test('test chained batch() with no operations is asynchronous', function (t) {
var Test = implement(AbstractLevelDOWN, {})
var test = new Test()
var async = false
test.batch().write(function (err) {
t.ifError(err, 'no error')
t.ok(async, 'callback is asynchronous')
t.end()
})
async = true
})
test('test chained batch() (custom _chainedBatch) extensibility', function (t) {
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, { _chainedBatch: spy })
var test = new Test('foobar')
test.batch()
t.equal(spy.callCount, 1, 'got _chainedBatch() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _chainedBatch() was correct')
test.batch()
t.equal(spy.callCount, 2, 'got _chainedBatch() call')
t.equal(spy.getCall(1).thisValue, test, '`this` on _chainedBatch() was correct')
t.end()
})
test('test AbstractChainedBatch extensibility', function (t) {
var Test = implement(AbstractChainedBatch)
var db = {}
var test = new Test(db)
t.ok(test.db === db, 'instance has db reference')
t.end()
})
test('test AbstractChainedBatch expects a db', function (t) {
t.plan(1)
var Test = implement(AbstractChainedBatch)
try {
Test()
} catch (err) {
t.is(err.message, 'First argument must be an abstract-leveldown compliant store')
}
})
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 })
test.write(spycb)
t.equal(spy.callCount, 1, 'got _write() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _write() was correct')
t.equal(spy.getCall(0).args.length, 2, 'got two arguments')
t.same(spy.getCall(0).args[0], {}, 'got options')
// awkward here cause of nextTick & an internal wrapped cb
t.equal(typeof spy.getCall(0).args[1], 'function', 'got a callback function')
t.equal(spycb.callCount, 0, 'spycb not called')
spy.getCall(0).args[1]()
t.equal(spycb.callCount, 1, 'spycb called, i.e. was our cb argument')
t.end()
})
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 })
test.write(null, function () {})
t.equal(spy.callCount, 1, 'got _write() call')
t.same(spy.getCall(0).args[0], {}, 'got options')
t.end()
})
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 })
test.write({ test: true }, function () {})
t.equal(spy.callCount, 1, 'got _write() call')
t.same(spy.getCall(0).args[0], { test: true }, 'got options')
t.end()
})
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)
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[0], expectedKey, 'got expected key argument')
t.equal(spy.getCall(0).args[1], expectedValue, 'got expected value 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)
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[0], expectedKey, 'got expected key 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()
t.equal(spy.callCount, 1, 'got _clear call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _clear() was correct')
t.equal(spy.getCall(0).args.length, 0, 'got zero arguments')
t.equal(returnValue, test, 'get expected return value')
t.end()
})
test('test iterator() extensibility', function (t) {
var spy = sinon.spy()
var expectedOptions = {
options: 1,
reverse: false,
keys: true,
values: true,
limit: -1,
keyAsBuffer: true,
valueAsBuffer: true
}
var Test = implement(AbstractLevelDOWN, { _iterator: spy })
var test = new Test('foobar')
test.iterator({ options: 1 })
t.equal(spy.callCount, 1, 'got _iterator() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _iterator() was correct')
t.equal(spy.getCall(0).args.length, 1, 'got one arguments')
t.deepEqual(spy.getCall(0).args[0], expectedOptions, 'got expected options argument')
t.end()
})
test('test AbstractIterator extensibility', function (t) {
var Test = implement(AbstractIterator)
var db = {}
var 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({})
test.next(spycb)
t.equal(spy.callCount, 1, 'got _next() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _next() was correct')
t.equal(spy.getCall(0).args.length, 1, 'got one arguments')
// awkward here cause of nextTick & an internal wrapped cb
t.equal(typeof spy.getCall(0).args[0], 'function', 'got a callback function')
t.equal(spycb.callCount, 0, 'spycb not called')
spy.getCall(0).args[0]()
t.equal(spycb.callCount, 1, 'spycb called, i.e. was our cb argument')
t.end()
})
test('test AbstractIterator#end() extensibility', function (t) {
var spy = sinon.spy()
var expectedCb = function () {}
var Test = implement(AbstractIterator, { _end: spy })
var test = new Test({})
test.end(expectedCb)
t.equal(spy.callCount, 1, 'got _end() call')
t.equal(spy.getCall(0).thisValue, test, '`this` on _end() was correct')
t.equal(spy.getCall(0).args.length, 1, 'got one arguments')
t.equal(spy.getCall(0).args[0], expectedCb, 'got expected cb argument')
t.end()
})
test('test clear() extensibility', function (t) {
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, { _clear: spy })
var db = new Test()
var callback = function () {}
call([callback], { reverse: false, limit: -1 })
call([null, callback], { reverse: false, limit: -1 })
call([undefined, callback], { reverse: false, limit: -1 })
call([{ custom: 1 }, callback], { custom: 1, reverse: false, limit: -1 })
call([{ reverse: true, limit: 0 }, callback], { reverse: true, limit: 0 })
call([{ reverse: 1 }, callback], { reverse: true, limit: -1 })
call([{ reverse: null }, callback], { reverse: false, limit: -1 })
function call (args, expectedOptions) {
db.clear.apply(db, args)
t.is(spy.callCount, 1, 'got _clear() call')
t.is(spy.getCall(0).thisValue, db, '`this` on _clear() was correct')
t.is(spy.getCall(0).args.length, 2, 'got two arguments')
t.same(spy.getCall(0).args[0], expectedOptions, 'got expected options argument')
t.is(spy.getCall(0).args[1], callback, 'got expected callback argument')
spy.resetHistory()
}
t.end()
})
test('test serialization extensibility (put)', function (t) {
t.plan(5)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_put: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.equal(value, 'nope')
return 'bar'
}
})
var test = new Test('foobar')
test.put('no', 'nope', function () {})
t.equal(spy.callCount, 1, 'got _put() call')
t.equal(spy.getCall(0).args[0], 'foo', 'got expected key argument')
t.equal(spy.getCall(0).args[1], 'bar', 'got expected value argument')
})
test('test serialization extensibility (del)', function (t) {
t.plan(3)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_del: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.fail('should not be called')
}
})
var test = new Test('foobar')
test.del('no', function () {})
t.equal(spy.callCount, 1, 'got _del() call')
t.equal(spy.getCall(0).args[0], 'foo', 'got expected key argument')
t.end()
})
test('test serialization extensibility (batch array put)', function (t) {
t.plan(5)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_batch: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.equal(value, 'nope')
return 'bar'
}
})
var test = new Test('foobar')
test.batch([{ type: 'put', key: 'no', value: 'nope' }], function () {})
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).args[0][0].key, 'foo', 'got expected key')
t.equal(spy.getCall(0).args[0][0].value, 'bar', 'got expected value')
})
test('test serialization extensibility (batch chain put)', function (t) {
t.plan(5)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_batch: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.equal(value, 'nope')
return 'bar'
}
})
var test = new Test('foobar')
test.batch().put('no', 'nope').write(function () {})
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).args[0][0].key, 'foo', 'got expected key')
t.equal(spy.getCall(0).args[0][0].value, 'bar', 'got expected value')
})
test('test serialization extensibility (batch array del)', function (t) {
t.plan(3)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_batch: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.fail('should not be called')
}
})
var test = new Test('foobar')
test.batch([{ type: 'del', key: 'no' }], function () {})
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).args[0][0].key, 'foo', 'got expected key')
})
test('test serialization extensibility (batch chain del)', function (t) {
t.plan(3)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_batch: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.fail('should not be called')
}
})
var test = new Test('foobar')
test.batch().del('no').write(function () {})
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).args[0][0].key, 'foo', 'got expected key')
})
test('test serialization extensibility (batch array is not mutated)', function (t) {
t.plan(7)
var spy = sinon.spy()
var Test = implement(AbstractLevelDOWN, {
_batch: spy,
_serializeKey: function (key) {
t.equal(key, 'no')
return 'foo'
},
_serializeValue: function (value) {
t.equal(value, 'nope')
return 'bar'
}
})
var test = new Test('foobar')
var op = { type: 'put', key: 'no', value: 'nope' }
test.batch([op], function () {})
t.equal(spy.callCount, 1, 'got _batch() call')
t.equal(spy.getCall(0).args[0][0].key, 'foo', 'got expected key')
t.equal(spy.getCall(0).args[0][0].value, 'bar', 'got expected value')
t.equal(op.key, 'no', 'did not mutate input key')
t.equal(op.value, 'nope', 'did not mutate input value')
})
test('test serialization extensibility (iterator range options)', function (t) {
t.plan(2)
function Test () {
AbstractLevelDOWN.call(this)
}
inherits(Test, AbstractLevelDOWN)
Test.prototype._serializeKey = function (key) {
t.is(key, 'input')
return 'output'
}
Test.prototype._iterator = function (options) {
return new Iterator(this, options)
}
function Iterator (db, options) {
AbstractIterator.call(this, db)
t.is(options.gt, 'output')
}
inherits(Iterator, AbstractIterator)
var 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 })
var Test = implement(AbstractLevelDOWN, {
_iterator: function () {
return new TestIterator(this)
},
_serializeKey: function (key) {
t.equal(key, 'target')
return 'serialized'
}
})
var test = new Test('foobar')
var it = test.iterator()
it.seek('target')
t.equal(spy.callCount, 1, 'got _seek() call')
t.equal(spy.getCall(0).args[0], 'serialized', 'got expected target argument')
})
test('test serialization extensibility (clear range options)', function (t) {
t.plan(rangeOptions.length * 2)
rangeOptions.forEach(function (key) {
var Test = implement(AbstractLevelDOWN, {
_serializeKey: function (key) {
t.is(key, 'input')
return 'output'
},
_clear: function (options, callback) {
t.is(options[key], 'output')
}
})
var db = new Test()
var options = {}
options[key] = 'input'
db.clear(options, function () {})
})
})
test('clear() does not delete empty or nullish range options', function (t) {
var rangeValues = [Buffer.alloc(0), '', null, undefined]
t.plan(rangeOptions.length * rangeValues.length)
rangeValues.forEach(function (value) {
var Test = implement(AbstractLevelDOWN, {
_clear: function (options, callback) {
rangeOptions.forEach(function (key) {
t.ok(key in options, key + ' option should not be deleted')
})
}
})
var db = new Test()
var options = {}
rangeOptions.forEach(function (key) {
options[key] = value
})
db.clear(options, function () {})
})
})
test('.status', function (t) {
t.plan(5)
t.test('empty prototype', function (t) {
var Test = implement(AbstractLevelDOWN)
var test = new Test('foobar')
t.equal(test.status, 'new')
test.open(function (err) {
t.error(err)
t.equal(test.status, 'open')
test.close(function (err) {
t.error(err)
t.equal(test.status, 'closed')
t.end()
})
})
})
t.test('open error', function (t) {
var Test = implement(AbstractLevelDOWN, {
_open: function (options, cb) {
cb(new Error())
}
})
var test = new Test('foobar')
test.open(function (err) {
t.ok(err)
t.equal(test.status, 'new')
t.end()
})
})
t.test('close error', function (t) {
var Test = implement(AbstractLevelDOWN, {
_close: function (cb) {
cb(new Error())
}
})
var test = new Test('foobar')
test.open(function () {
test.close(function (err) {
t.ok(err)
t.equal(test.status, 'open')
t.end()
})
})
})
t.test('open', function (t) {
var Test = implement(AbstractLevelDOWN, {
_open: function (options, cb) {
process.nextTick(cb)
}
})
var test = new Test('foobar')
test.open(function (err) {
t.error(err)
t.equal(test.status, 'open')
t.end()
})
t.equal(test.status, 'opening')
})
t.test('close', function (t) {
var Test = implement(AbstractLevelDOWN, {
_close: function (cb) {
process.nextTick(cb)
}
})
var test = new Test('foobar')
test.open(function (err) {
t.error(err)
test.close(function (err) {
t.error(err)
t.equal(test.status, 'closed')
t.end()
})
t.equal(test.status, 'closing')
})
})
})
test('_setupIteratorOptions', function (t) {
var keys = legacyRangeOptions.concat(rangeOptions)
var db = new AbstractLevelDOWN()
function setupOptions (constrFn) {
var options = {}
keys.forEach(function (key) {
options[key] = constrFn()
})
return options
}
function verifyOptions (t, options) {
keys.forEach(function (key) {
t.ok(key in options, key + ' option should not be deleted')
})
t.end()
}
t.plan(6)
t.test('default options', function (t) {
t.same(db._setupIteratorOptions(), {
reverse: false,
keys: true,
values: true,
limit: -1,
keyAsBuffer: true,
valueAsBuffer: true
}, 'correct defaults')
t.end()
})
t.test('set options', function (t) {
t.same(db._setupIteratorOptions({
reverse: false,
keys: false,
values: false,
limit: 20,
keyAsBuffer: false,
valueAsBuffer: false
}), {
reverse: false,
keys: false,
values: false,
limit: 20,
keyAsBuffer: false,
valueAsBuffer: false
}, 'options set correctly')
t.end()
})
t.test('does not delete empty buffers', function (t) {
var 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')
})
verifyOptions(t, db._setupIteratorOptions(options))
})
t.test('does not delete empty strings', function (t) {
var 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')
})
verifyOptions(t, db._setupIteratorOptions(options))
})
t.test('does not delete null', function (t) {
var options = setupOptions(function () { return null })
keys.forEach(function (key) {
t.is(options[key], null, 'should be null')
})
verifyOptions(t, db._setupIteratorOptions(options))
})
t.test('does not delete undefined', function (t) {
var options = setupOptions(function () { return undefined })
keys.forEach(function (key) {
t.is(options[key], undefined, 'should be undefined')
})
verifyOptions(t, db._setupIteratorOptions(options))
})
})
abstract-leveldown-6.2.2/test/util.js 0000664 0000000 0000000 00000000546 13553424167 0017632 0 ustar 00root root 0000000 0000000 var nfre = /NotFound/i
exports.verifyNotFoundError = function verifyNotFoundError (err) {
return nfre.test(err.message) || nfre.test(err.name)
}
exports.isTypedArray = function isTypedArray (value) {
return (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) ||
(typeof Uint8Array !== 'undefined' && value instanceof Uint8Array)
}