Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial import

  • Loading branch information...
commit 5dc05673ceeafde4a7e796493718043e56e39667 0 parents
@rvagg rvagg authored
1  .gitignore
@@ -0,0 +1 @@
+node_modules
61 .jshintrc
@@ -0,0 +1,61 @@
+{
+ "predef": [ ]
+ , "bitwise": false
+ , "camelcase": false
+ , "curly": false
+ , "eqeqeq": false
+ , "forin": false
+ , "immed": false
+ , "latedef": false
+ , "newcap": true
+ , "noarg": true
+ , "noempty": true
+ , "nonew": true
+ , "plusplus": false
+ , "quotmark": true
+ , "regexp": false
+ , "undef": true
+ , "unused": true
+ , "strict": false
+ , "trailing": true
+ , "maxlen": 120
+ , "asi": true
+ , "boss": true
+ , "debug": true
+ , "eqnull": true
+ , "es5": true
+ , "esnext": true
+ , "evil": true
+ , "expr": true
+ , "funcscope": false
+ , "globalstrict": false
+ , "iterator": false
+ , "lastsemic": true
+ , "laxbreak": true
+ , "laxcomma": true
+ , "loopfunc": true
+ , "multistr": false
+ , "onecase": false
+ , "proto": false
+ , "regexdash": false
+ , "scripturl": true
+ , "smarttabs": false
+ , "shadow": false
+ , "sub": true
+ , "supernew": false
+ , "validthis": true
+ , "browser": true
+ , "couch": false
+ , "devel": false
+ , "dojo": false
+ , "mootools": false
+ , "node": true
+ , "nonstandard": true
+ , "prototypejs": false
+ , "rhino": false
+ , "worker": true
+ , "wsh": false
+ , "nomen": false
+ , "onevar": true
+ , "passfail": false
+}
9 .travis.yml
@@ -0,0 +1,9 @@
+language: node_js
+node_js:
+ - 0.8
+branches:
+ only:
+ - master
+notifications:
+ email:
+ - rod@vagg.org
39 LICENSE
@@ -0,0 +1,39 @@
+Copyright 2013, Rod Vagg (the "Original Author")
+All rights reserved.
+
+MIT +no-false-attribs License
+
+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.
+
+Distributions of all or part of the Software intended to be used
+by the recipients as they would use the unmodified Software,
+containing modifications that substantially alter, remove, or
+disable functionality of the Software, outside of the documented
+configuration mechanisms provided by the Software, shall be
+modified such that the Original Author's bug reporting email
+addresses and urls are either replaced with the contact information
+of the parties responsible for the changes, or removed entirely.
+
+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.
+
+
+Except where noted, this license applies to any and all software
+programs and associated documentation files created by the
+Original Author, when distributed with the Software.
106 README.md
@@ -0,0 +1,106 @@
+# Abstract LevelDOWN [![Build Status](https://secure.travis-ci.org/rvagg/node-abstract-leveldown.png)](http://travis-ci.org/rvagg/node-abstract-leveldown)
+
+An abstract prototype matching the [LevelDOWN](https://github.com/rvagg/node-leveldown/) API. Useful for extending [LevelUP](https://github.com/rvagg/node-levelup) functionality by providing a replacement to LevelDOWN.
+
+**Abstract LevelDOWN** provides a simple, operational *noop* base prototype that's ready for extending. By default, all operations have sensible "noops" (operations that essentially do nothing). For example, simple operations such as `.open(callback)` and `.close(callback)` will simply invoke the callback (on a *next tick*). More complex operations perform sensible actions, for example: `.get(key, callback)` will always return a `'NotFound'` `Error` on the callback.
+
+You add functionality by implementing the underscore versions of the operations. For example, to implement a `put()` operation you add a `_put()` method to your object. Each of these underscore methods override the default *noop* operations and are always provided with **consistent arguments**, regardless of what is passed in by the client.
+
+Additionally, all methods provide argument checking and sensible defaults for optional arguments. All bad-argument errors are compatible with LevelDOWN (they pass the LevelDOWN method arguments tests). For example, if you call `.open()` without a callback argument you'll get an `Error('open() requires a callback argument')`. Where optional arguments are involved, your underscore methods will receive sensible defaults. A `.get(key, callback)` will pass through to a `._get(key, options, callback)` where the `options` argument is an empty object.
+
+## Example
+
+A simplistic in-memory LevelDOWN replacement
+
+```js
+var util = require('util')
+ , AbstractLevelDOWN = require('./').AbstractLevelDOWN
+
+// constructor, passes through the 'location' argument to the AbstractLevelDOWN constructor
+function FakeLevelDOWN (location) {
+ AbstractLevelDOWN.call(this, location)
+}
+
+// our new prototype inherits from AbstractLevelDOWN
+util.inherits(FakeLevelDOWN, AbstractLevelDOWN)
+
+// implement some methods
+
+FakeLevelDOWN.prototype._open = function (options, callback) {
+ // initialise a memory storage object
+ this._store = {}
+ // optional use of nextTick to be a nice async citizen
+ process.nextTick(function () { callback(null, this) }.bind(this))
+}
+
+FakeLevelDOWN.prototype._put = function (key, value, options, callback) {
+ key = '$' + key // safety, to avoid key='__proto__'-type skullduggery
+ 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(function () { callback(new Error('NotFound')) })
+ }
+ process.nextTick(function () {
+ callback(null, value)
+ })
+}
+
+FakeLevelDOWN.prototype._del = function (key, options, callback) {
+ delete this._store['$' + key]
+ process.nextTick(callback)
+}
+
+// now use it in LevelUP
+
+var levelup = require('levelup')
+
+var db = levelup('/who/cares/', {
+ // the 'db' option replaces LevelDOWN
+ db: function (location) { return new FakeLevelDOWN(location) }
+})
+
+db.put('foo', 'bar', function (err) {
+ if (err) throw err
+ db.get('foo', function (err, value) {
+ if (err) throw err
+ console.log('Got foo =', value)
+ })
+})
+```
+
+## Extensible API
+
+Remember that each of these methods, if you implement them, will receive exactly the number and order of arguments described. Optional arguments will be converted to sensible defaults.
+
+### AbstractLevelDOWN(location)
+### AbstractLevelDOWN#_open(options, callback)
+### AbstractLevelDOWN#_close(callback)
+### AbstractLevelDOWN#_get(key, options, callback)
+### AbstractLevelDOWN#_put(key, value, options, callback)
+### AbstractLevelDOWN#_del(key, options, callback)
+### AbstractLevelDOWN#_batch(array, options, callback)
+
+Note: At the time of writing, the LevelDOWN `batch()` API is in flux, see the 2.0-wip branch. If `batch()` is called without argument or with only an options object then it should return a `Batch` object with chainable methods. Otherwise it will invoke a classic batch operation.
+
+### AbstractLevelDOWN#_approximateSize(start, end, callback)
+### AbstractLevelDOWN#_iterator(options)
+
+By default an `iterator()` operation returns a blank `AbstractIterator` object. The prototype is available on the main exports for you to extend. If you want to implement iterator operations then you should extend the `AbstractIterator` and return your object in the `_iterator(options)` method.
+
+`AbstractIterator` implements the basic state management found in LevelDOWN. It 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 it allow `end()` while a `next()` is in progress and it doesn't allow either `next()` or `end()` after `end()` has been called.
+
+### AbstractIterator(db)
+
+Provided with the current instance of `AbstractLevelDOWN` by default.
+
+### AbstractIterator#next(callback)
+### AbstractIterator#end(callback)
+
+## Licence
+
+Abstract LevelDOWN is Copyright (c) 2013 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licensed under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
165 abstract-leveldown.js
@@ -0,0 +1,165 @@
+/* Copyright (c) 2013 Rod Vagg, MIT License */
+
+function AbstractIterator (db) {
+ this.db = db
+ this._ended = false
+ this._nexting = false
+}
+
+AbstractIterator.prototype.next = function (callback) {
+ if (typeof callback != 'function')
+ throw new Error('next() requires a callback argument')
+
+ if (this._ended)
+ throw new Error('cannot call next() after end()')
+ if (this._nexting)
+ throw new Error('cannot call next() before previous next() has completed')
+
+ this._nexting = true
+ if (typeof this._next == 'function') {
+ return this._next(function () {
+ this._nexting = false
+ callback.apply(null, arguments)
+ }.bind(this))
+ }
+
+ process.nextTick(function () {
+ this._nexting = false
+ callback()
+ }.bind(this))
+}
+
+AbstractIterator.prototype.end = function (callback) {
+ if (typeof callback != 'function')
+ throw new Error('end() requires a callback argument')
+
+ if (this._ended)
+ throw new Error('end() already called on iterator')
+
+ this._ended = true
+
+ if (typeof this._end == 'function')
+ return this._end(callback)
+
+ process.nextTick(callback)
+}
+
+function AbstractLevelDOWN (location) {
+ if (!arguments.length || location === undefined)
+ throw new Error('leveldown() requires at least a location argument')
+
+ if (typeof location != 'string')
+ throw new Error('leveldown() requires a location string argument')
+
+ this.location = location
+}
+
+AbstractLevelDOWN.prototype.open = function (options, callback) {
+ if (typeof options == 'function')
+ callback = options
+ if (typeof callback != 'function')
+ throw new Error('open() requires a callback argument')
+ if (typeof options != 'object')
+ options = {}
+
+ if (typeof this._open == 'function')
+ return this._open(options, callback)
+
+ process.nextTick(callback)
+}
+
+AbstractLevelDOWN.prototype.close = function (callback) {
+ if (typeof callback != 'function')
+ throw new Error('close() requires a callback argument')
+
+ if (typeof this._close == 'function')
+ return this._close(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')
+ if (typeof options != 'object')
+ options = {}
+
+ if (typeof this._get == 'function')
+ return this._get(key, options, callback)
+
+ process.nextTick(callback.bind(null, 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')
+ if (typeof options != 'object')
+ options = {}
+
+ if (typeof this._put == 'function')
+ return this._put(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')
+ if (typeof options != 'object')
+ options = {}
+
+
+ if (typeof this._del == 'function')
+ return this._del(key, options, callback)
+
+ process.nextTick(callback)
+}
+
+AbstractLevelDOWN.prototype.batch = function (array, options, callback) {
+ if (typeof options == 'function')
+ callback = options
+ if (!Array.isArray(array) && typeof array == 'object') {
+ options = array
+ array = undefined
+ }
+ if (typeof options != 'object')
+ options = {}
+
+ // TODO: if array == undefined && callback == function, derp
+
+ if (typeof this._batch == 'function')
+ return this._batch(array, options, callback)
+
+ process.nextTick(callback)
+}
+
+AbstractLevelDOWN.prototype.approximateSize = function (start, end, callback) {
+ if (start == null || end == null || typeof start == 'function' || typeof end == 'function')
+ throw new Error('approximateSize() requires valid `start`, `end` and `callback` arguments')
+ if (typeof callback != 'function')
+ throw new Error('approximateSize() requires a callback argument')
+
+ if (typeof this._approximateSize == 'function')
+ return this._approximateSize(start, end, callback)
+
+ process.nextTick(callback.bind(null, null, 0))
+}
+
+AbstractLevelDOWN.prototype.iterator = function (options) {
+ if (typeof options != 'object')
+ options = {}
+
+ if (typeof this._iterator == 'function')
+ return this._iterator(options)
+
+ return new AbstractIterator(this)
+}
+
+module.exports.AbstractLevelDOWN = AbstractLevelDOWN
+module.exports.AbstractIterator = AbstractIterator
26 package.json
@@ -0,0 +1,26 @@
+{
+ "name" : "abstract-leveldown"
+ , "description" : "An abstract prototype matching the LevelDOWN API"
+ , "version" : "0.0.0"
+ , "homepage" : "https://github.com/rvagg/node-abstract-leveldown"
+ , "authors" : [
+ "Rod Vagg <rod@vagg.org> (https://github.com/rvagg)"
+ ]
+ , "keywords" : [ "leveldb", "leveldown", "levelup" ]
+ , "main" : "./abstract-leveldown.js"
+ , "repository" : {
+ "type" : "git"
+ , "url" : "https://github.com/rvagg/node-abstract-leveldown.git"
+ }
+ , "dependencies" : {
+ }
+ , "devDependencies" : {
+ "tap" : "*"
+ , "leveldown" : "~0.2.0"
+ , "sinon" : "*"
+ }
+ , "scripts": {
+ "test" : "node ./test.js"
+ }
+ , "license" : "MIT"
+}
382 test.js
@@ -0,0 +1,382 @@
+var tap = require('tap')
+ , sinon = require('sinon')
+ , util = require('util')
+ , AbstractLevelDOWN = require('./').AbstractLevelDOWN
+ , AbstractIterator = require('./').AbstractIterator
+
+ , factory = function (location) {
+ return new AbstractLevelDOWN(location)
+ }
+
+/*** compatibility with basic LevelDOWN API ***/
+
+require('leveldown/test/leveldown-test').args(factory)
+
+require('leveldown/test/open-test').args(factory)
+
+require('leveldown/test/del-test').setUp(factory)
+require('leveldown/test/del-test').args(factory)
+
+require('leveldown/test/get-test').setUp(factory)
+require('leveldown/test/get-test').args(factory)
+
+require('leveldown/test/put-test').setUp(factory)
+require('leveldown/test/put-test').args(factory)
+
+require('leveldown/test/approximate-size-test').setUp(factory)
+require('leveldown/test/approximate-size-test').args(factory)
+
+require('leveldown/test/close-test').close(factory)
+
+require('leveldown/test/iterator-test').setUp(factory)
+require('leveldown/test/iterator-test').args(factory)
+require('leveldown/test/iterator-test').sequence(factory)
+
+/*** extensibility ***/
+
+tap.test('test core extensibility', function (t) {
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ t.equal(this.location, location, 'location set on `this`')
+ t.end()
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ ;new Test('foobar')
+})
+
+tap.test('test open() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedOptions = { options: 1 }
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._open = spy
+
+ 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], {}, 'got blank options argument')
+ t.equal(spy.getCall(0).args[1], expectedCb, 'got expected cb argument')
+
+ test.open(expectedOptions, expectedCb)
+
+ 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 blank options argument')
+ t.equal(spy.getCall(1).args[1], expectedCb, 'got expected cb argument')
+ t.end()
+})
+
+tap.test('test close() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._close = spy
+
+ 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.equal(spy.getCall(0).args[0], expectedCb, 'got expected cb argument')
+ t.end()
+})
+
+tap.test('test get() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedOptions = { options: 1 }
+ , expectedKey = 'a key'
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._get = spy
+
+ 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], {}, 'got blank options argument')
+ t.equal(spy.getCall(0).args[2], expectedCb, 'got expected cb argument')
+
+ test.get(expectedKey, expectedOptions, expectedCb)
+
+ 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 blank options argument')
+ t.equal(spy.getCall(1).args[2], expectedCb, 'got expected cb argument')
+ t.end()
+})
+
+tap.test('test del() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedOptions = { options: 1 }
+ , expectedKey = 'a key'
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._del = spy
+
+ 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 blank options argument')
+ t.equal(spy.getCall(1).args[2], expectedCb, 'got expected cb argument')
+ t.end()
+})
+
+tap.test('test put() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedOptions = { options: 1 }
+ , expectedKey = 'a key'
+ , expectedValue = 'a value'
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._put = spy
+
+ 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()
+})
+
+tap.test('test approximateSize() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedStart = 'a start'
+ , expectedEnd = 'an end'
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._approximateSize = spy
+
+ test = new Test('foobar')
+ test.approximateSize(expectedStart, expectedEnd, expectedCb)
+
+ t.equal(spy.callCount, 1, 'got _approximateSize() call')
+ t.equal(spy.getCall(0).thisValue, test, '`this` on _approximateSize() was correct')
+ t.equal(spy.getCall(0).args.length, 3, 'got three arguments')
+ t.equal(spy.getCall(0).args[0], expectedStart, 'got expected start argument')
+ t.equal(spy.getCall(0).args[1], expectedEnd, 'got expected end argument')
+ t.equal(spy.getCall(0).args[2], expectedCb, 'got expected cb argument')
+ t.end()
+})
+
+tap.test('test batch() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , expectedOptions = { options: 1 }
+ , expectedArray = [ 1, 2 ]
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._batch = spy
+
+ test = new Test('foobar')
+
+ test.batch()
+
+ 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], undefined, 'got expected array argument')
+ t.deepEqual(spy.getCall(0).args[1], {}, 'got blank options argument')
+ t.equal(spy.getCall(0).args[2], undefined, 'got expected callback argument')
+
+ test.batch(expectedOptions)
+
+ 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], undefined, 'got expected array argument')
+ t.deepEqual(spy.getCall(1).args[1], expectedOptions, 'got expected options argument')
+ t.equal(spy.getCall(1).args[2], undefined, 'got expected callback argument')
+
+ test.batch(expectedArray, 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.equal(spy.getCall(2).args[0], expectedArray, 'got expected array argument')
+ t.deepEqual(spy.getCall(2).args[1], {}, 'got expected options argument')
+ t.equal(spy.getCall(2).args[2], expectedCb, 'got expected callback argument')
+
+ test.batch(expectedArray, expectedOptions, expectedCb)
+
+ t.equal(spy.callCount, 4, 'got _batch() call')
+ t.equal(spy.getCall(3).thisValue, test, '`this` on _batch() was correct')
+ t.equal(spy.getCall(3).args.length, 3, 'got three arguments')
+ t.equal(spy.getCall(3).args[0], expectedArray, 'got expected array argument')
+ t.deepEqual(spy.getCall(3).args[1], expectedOptions, 'got expected options argument')
+ t.equal(spy.getCall(3).args[2], expectedCb, 'got expected callback argument')
+
+ t.end()
+})
+
+tap.test('test iterator() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedOptions = { options: 1 }
+ , test
+
+ function Test (location) {
+ AbstractLevelDOWN.call(this, location)
+ }
+
+ util.inherits(Test, AbstractLevelDOWN)
+
+ Test.prototype._iterator = spy
+
+ test = new Test('foobar')
+ test.iterator(expectedOptions)
+
+ 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.equal(spy.getCall(0).args[0], expectedOptions, 'got expected options argument')
+ t.end()
+})
+
+tap.test('test AbstractIterator extensibility', function (t) {
+ function Test (db) {
+ AbstractIterator.call(this, db)
+ t.equal(this.db, db, 'db set on `this`')
+ t.end()
+ }
+
+ util.inherits(Test, AbstractIterator)
+
+ ;new Test('foobar')
+})
+
+tap.test('test next() extensibility', function (t) {
+ var spy = sinon.spy()
+ , spycb = sinon.spy()
+ , test
+
+ function Test (db) {
+ AbstractIterator.call(this, db)
+ }
+
+ util.inherits(Test, AbstractIterator)
+
+ Test.prototype._next = spy
+
+ test = new Test('foobar')
+ 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.type(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()
+})
+
+tap.test('test end() extensibility', function (t) {
+ var spy = sinon.spy()
+ , expectedCb = function () {}
+ , test
+
+ function Test (db) {
+ AbstractIterator.call(this, db)
+ }
+
+ util.inherits(Test, AbstractIterator)
+
+ Test.prototype._end = spy
+
+ test = new Test('foobar')
+ 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()
+})
Please sign in to comment.
Something went wrong with that request. Please try again.