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

Address a few TODO comments in the test suite #97

Merged
merged 1 commit into from
Dec 29, 2024
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
25 changes: 21 additions & 4 deletions test/iterator-seek-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,26 @@ exports.sequence = function (test, testCommon) {

exports.seek = function (test, testCommon) {
const testData = () => [
// Note that 'three' sorts before 'two'
{ type: 'put', key: 'one', value: '1' },
{ type: 'put', key: 'two', value: '2' },
{ type: 'put', key: 'three', value: '3' }
]

const bufferTestData = () => [
// Note that 'b9' sorts before 'c0'
{ type: 'put', key: Buffer.from('80', 'hex'), value: '1', keyEncoding: 'buffer' },
{ type: 'put', key: Buffer.from('c0', 'hex'), value: '2', keyEncoding: 'buffer' },
{ type: 'put', key: Buffer.from('b9', 'hex'), value: '3', keyEncoding: 'buffer' }
]

test('prepare byte-aware tests', function (t) {
const data = bufferTestData()
t.ok(data[0].key.toString() === data[1].key.toString(), 'would be equal when not byte-aware')
t.ok(data[0].key.compare(data[1].key) < 0, 'but less than when byte-aware')
t.end()
})

for (const mode of ['iterator', 'keys', 'values']) {
const mapEntry = mode === 'iterator' ? e => e : mode === 'keys' ? e => e[0] : e => e[1]

Expand All @@ -63,15 +78,17 @@ exports.seek = function (test, testCommon) {
})

if (testCommon.supports.encodings.buffer) {
// TODO: make this test meaningful, with bytes outside the utf8 range
test(`${mode}().seek() to buffer target`, async function (t) {
// For this test to be meaningful it must use bytes outside the utf8 range
const data = bufferTestData()
const db = testCommon.factory()
await db.batch(testData())
await db.batch(data)
const it = db[mode]({ keyEncoding: 'buffer' })

it.seek(Buffer.from('two'))
// Seek to second key
it.seek(data[1].key)

t.same(await it.next(), mapEntry([Buffer.from('two'), '2']), 'match')
t.same(await it.next(), mapEntry([data[1].key, '2']), 'match')
t.same(await it.next(), undefined, 'end of iterator')

return db.close()
Expand Down
71 changes: 35 additions & 36 deletions test/self/deferred-iterator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ for (const mode of ['iterator', 'keys', 'values']) {
})

// NOTE: adapted from deferred-leveldown
test(`deferred ${mode}(): non-deferred operations`, function (t) {
t.plan(4)
test(`deferred ${mode}(): non-deferred operations`, async function (t) {
t.plan(3)

class MockIterator extends RealCtor {
_seek (target) {
Expand All @@ -74,17 +74,14 @@ for (const mode of ['iterator', 'keys', 'values']) {
}
})

// TODO: async/await
db.open().then(function () {
it.seek(123)
it.next().then(function (item) {
t.is(item, nextArg)
it.close().then(t.pass.bind(t, 'closed'))
})
})

const it = db[publicMethod]({ gt: 'foo' })
t.ok(it instanceof DeferredCtor)

await db.open()
it.seek(123)
t.is(await it.next(), nextArg)

return it.close()
})

// NOTE: adapted from deferred-leveldown
Expand Down Expand Up @@ -127,7 +124,7 @@ for (const mode of ['iterator', 'keys', 'values']) {
})

for (const method of ['next', 'nextv', 'all']) {
test(`deferred ${mode}(): closed upon failed open, verified by ${method}()`, function (t) {
test(`deferred ${mode}(): closed upon failed open, verified by ${method}()`, async function (t) {
t.plan(5)

const db = mockLevel({
Expand All @@ -152,11 +149,11 @@ for (const mode of ['iterator', 'keys', 'values']) {
return original.call(this, ...args)
}

verifyClosed(t, it, method, () => {})
return verifyClosed(t, it, method)
})

test(`deferred ${mode}(): deferred and real iterators are closed on db.close(), verified by ${method}()`, function (t) {
t.plan(8)
test(`deferred ${mode}(): deferred and real iterators are closed on db.close(), verified by ${method}()`, async function (t) {
t.plan(7)

class MockIterator extends RealCtor {
async _close () {
Expand All @@ -179,17 +176,16 @@ for (const mode of ['iterator', 'keys', 'values']) {
return original.call(this, ...args)
}

// TODO: async/await
db.open().then(() => db.close()).then(function () {
verifyClosed(t, it, method, function () {
db.open().then(function () {
// Should still be closed
verifyClosed(t, it, method, function () {
db.close().then(t.pass.bind(t))
})
})
})
})
await db.open()
await db.close()

await verifyClosed(t, it, method)
await db.open()

// Should still be closed
await verifyClosed(t, it, method)

return db.close()
})
}

Expand Down Expand Up @@ -298,18 +294,21 @@ for (const mode of ['iterator', 'keys', 'values']) {
})
})

// TODO: async/await
const verifyClosed = function (t, it, method, cb) {
const verifyClosed = async function (t, it, method) {
const requiredArgs = method === 'nextv' ? [10] : []

it[method](...requiredArgs).then(t.fail.bind(t, 'should not succeed'), function (err) {
t.is(err && err.code, 'LEVEL_ITERATOR_NOT_OPEN', `correct error on first ${method}()`)
try {
await it[method](...requiredArgs)
t.fail('should not succeed')
} catch (err) {
t.is(err.code, 'LEVEL_ITERATOR_NOT_OPEN', `correct error on first ${method}()`)
}

// Should account for userland code that ignores errors
it[method](...requiredArgs).then(t.fail.bind(t, 'should not succeed'), function (err) {
t.is(err && err.code, 'LEVEL_ITERATOR_NOT_OPEN', `correct error on second ${method}()`)
cb()
})
})
try {
await it[method](...requiredArgs)
t.fail('should not succeed')
} catch (err) {
t.is(err.code, 'LEVEL_ITERATOR_NOT_OPEN', `correct error on second ${method}()`)
}
}
}
114 changes: 54 additions & 60 deletions test/self/sublevel-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,25 @@ test('sublevel is extensible', function (t) {
})

// NOTE: adapted from subleveldown
test('sublevel prefix and options', function (t) {
// TODO: rename "prefix" to "name" where appropriate. E.g. this test should be
// called 'empty name' rather than 'empty prefix'.
t.test('empty prefix', function (t) {
test('sublevel name and options', function (t) {
t.test('empty name', function (t) {
const sub = new NoopLevel().sublevel('')
t.is(sub.prefix, '!!')
t.same(sub.path(), [''])
t.end()
})

t.test('prefix without options', function (t) {
const sub = new NoopLevel().sublevel('prefix')
t.is(sub.prefix, '!prefix!')
t.same(sub.path(), ['prefix'])
t.test('name without options', function (t) {
const sub = new NoopLevel().sublevel('name')
t.is(sub.prefix, '!name!')
t.same(sub.path(), ['name'])
t.end()
})

t.test('prefix and separator option', function (t) {
const sub = new NoopLevel().sublevel('prefix', { separator: '%' })
t.is(sub.prefix, '%prefix%')
t.same(sub.path(), ['prefix'])
t.test('name and separator option', function (t) {
const sub = new NoopLevel().sublevel('name', { separator: '%' })
t.is(sub.prefix, '%name%')
t.same(sub.path(), ['name'])
t.end()
})

Expand Down Expand Up @@ -140,22 +138,22 @@ test('sublevel prefix and options', function (t) {
t.end()
})

t.test('separator is trimmed from prefix', function (t) {
const sub1 = new NoopLevel().sublevel('!prefix')
t.is(sub1.prefix, '!prefix!')
t.same(sub1.path(), ['prefix'])
t.test('separator is trimmed from name', function (t) {
const sub1 = new NoopLevel().sublevel('!name')
t.is(sub1.prefix, '!name!')
t.same(sub1.path(), ['name'])

const sub2 = new NoopLevel().sublevel('prefix!')
t.is(sub2.prefix, '!prefix!')
t.same(sub2.path(), ['prefix'])
const sub2 = new NoopLevel().sublevel('name!')
t.is(sub2.prefix, '!name!')
t.same(sub2.path(), ['name'])

const sub3 = new NoopLevel().sublevel('!!prefix!!')
t.is(sub3.prefix, '!prefix!')
t.same(sub3.path(), ['prefix'])
const sub3 = new NoopLevel().sublevel('!!name!!')
t.is(sub3.prefix, '!name!')
t.same(sub3.path(), ['name'])

const sub4 = new NoopLevel().sublevel('@prefix@', { separator: '@' })
t.is(sub4.prefix, '@prefix@')
t.same(sub4.path(), ['prefix'])
const sub4 = new NoopLevel().sublevel('@name@', { separator: '@' })
t.is(sub4.prefix, '@name@')
t.same(sub4.path(), ['name'])

const sub5 = new NoopLevel().sublevel(['!!!a', 'b!!!'])
t.is(sub5.prefix, '!a!!b!')
Expand Down Expand Up @@ -615,7 +613,7 @@ test('sublevel operations are prefixed', function (t) {

test('sublevel encodings', function (t) {
// NOTE: adapted from subleveldown
t.test('different sublevels can have different encodings', function (t) {
t.test('different sublevels can have different encodings', async function (t) {
t.plan(6)

const puts = []
Expand All @@ -636,41 +634,37 @@ test('sublevel encodings', function (t) {
const sub1 = db.sublevel('test1', { valueEncoding: 'json' })
const sub2 = db.sublevel('test2', { keyEncoding: 'buffer', valueEncoding: 'buffer' })

// TODO: async/await
sub1.put('foo', { some: 'json' }).then(function () {
t.same(puts, [{
key: '!test1!foo',
value: '{"some":"json"}',
keyEncoding: 'utf8',
valueEncoding: 'utf8'
}])

sub1.get('foo').then(function (value) {
t.same(value, { some: 'json' })
t.same(gets.shift(), {
key: '!test1!foo',
keyEncoding: 'utf8',
valueEncoding: 'utf8'
})
await sub1.put('foo', { some: 'json' })

sub2.put(Buffer.from([1, 2]), Buffer.from([3])).then(function () {
t.same(puts, [{
key: Buffer.from('!test2!\x01\x02'),
value: Buffer.from([3]),
keyEncoding: 'buffer',
valueEncoding: 'buffer'
}])

sub2.get(Buffer.from([1, 2])).then(function (value) {
t.same(value, Buffer.from([3]))
t.same(gets.shift(), {
key: Buffer.from('!test2!\x01\x02'),
keyEncoding: 'buffer',
valueEncoding: 'buffer'
})
})
})
})
t.same(puts, [{
key: '!test1!foo',
value: '{"some":"json"}',
keyEncoding: 'utf8',
valueEncoding: 'utf8'
}])

t.same(await sub1.get('foo'), { some: 'json' })
t.same(gets.shift(), {
key: '!test1!foo',
keyEncoding: 'utf8',
valueEncoding: 'utf8'
})

await sub2.put(Buffer.from([1, 2]), Buffer.from([3]))

t.same(puts, [{
key: Buffer.from('!test2!\x01\x02'),
value: Buffer.from([3]),
keyEncoding: 'buffer',
valueEncoding: 'buffer'
}])

t.same(await sub2.get(Buffer.from([1, 2])), Buffer.from([3]))

t.same(gets.shift(), {
key: Buffer.from('!test2!\x01\x02'),
keyEncoding: 'buffer',
valueEncoding: 'buffer'
})
})

Expand Down
Loading