Skip to content

Commit

Permalink
Import seek tests from leveldown (#307)
Browse files Browse the repository at this point in the history
* import seek tests from leveldown

* avoid util.format in seek tests

* don't use make() for 'iterator seek respects range' test

* normalize seek test names

* include iterator#seek() sequence tests in own tests

* optionally skip 'iterator#seek() to buffer target' test

* assert next() is async in seek sequence test
  • Loading branch information
vweevers authored Oct 19, 2018
1 parent e7285bb commit b610da0
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 0 deletions.
4 changes: 4 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ function suite (options) {
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 {
Expand Down
281 changes: 281 additions & 0 deletions test/iterator-seek-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
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)
}
4 changes: 4 additions & 0 deletions test/self.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ 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)

function implement (ctor, methods) {
function Test () {
ctor.apply(this, arguments)
Expand Down

0 comments on commit b610da0

Please sign in to comment.