Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import seek tests from leveldown #307

Merged
merged 7 commits into from
Oct 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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?
vweevers marked this conversation as resolved.
Show resolved Hide resolved
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