Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mafintosh committed Sep 8, 2024
1 parent b80bf8b commit 8073ced
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 30 deletions.
12 changes: 11 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class Updates {
class HyperDB {
constructor (engine, definition, {
version = definition.version,
snapshot = null,
snapshot = engine.snapshot(),
updates = new Updates([])
} = {}) {
this.version = version
Expand All @@ -106,6 +106,10 @@ class HyperDB {
engine.refs++
}

static isDefinition (definition) {
return !!(definition && typeof definition.resolveCollection === 'function')
}

static rocksdb (storage, definition, opts) {
return new HyperDB(new RocksEngine(storage), definition, opts)
}
Expand Down Expand Up @@ -277,9 +281,15 @@ class HyperDB {
if (this.updates.size === 0) return
if (this._engineClock !== this.engine.clock) throw new Error('Database has changed, refusing to commit')
if (this.updates.refs > 1) this.updates = this.updates.detach()

await this.engine.commit(this.updates)
this._engineClock = this.engine.clock
this.updates.clear()

if (this._engineSnapshot) {
this._engineSnapshot.unref()
this._engineSnapshot = this.engine.snapshot()
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/engine/rocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ module.exports = class RocksEngine {
this.db = typeof storage === 'object' ? storage : new RocksDB(storage)
}

get closed () {
return this.db.closed
}

ready () {
return this.db.ready()
}
Expand Down
26 changes: 25 additions & 1 deletion lib/stream.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { Readable, isEnded } = require('streamx')
const { Readable, isEnded, getStreamError } = require('streamx')
const b4a = require('b4a')

module.exports = class IndexStream extends Readable {
Expand Down Expand Up @@ -148,6 +148,30 @@ module.exports = class IndexStream extends Readable {
this.continueDestroy = cb
this._continueDestroyMaybe()
}

async toArray () {
const list = []
const stream = this

return new Promise(function (resolve, reject) {
stream.on('error', noop)
stream.on('readable', onreadable)
stream.on('close', onclose)

function onreadable () {
while (true) {
const data = stream.read()
if (data === null) return
list.push(data)
}
}

function onclose () {
if (isEnded(stream)) resolve(list)
else reject(getStreamError(stream, { all: true }))
}
})
}
}

function fullyDrainMapped (stream) {
Expand Down
45 changes: 21 additions & 24 deletions test/basic.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
const HyperDB = require('../')
const definition = require('./fixtures/definition')
const generatedDefinition = require('./fixtures/generated')
const tmp = require('test-tmp')
const test = require('brittle')
const { collect } = require('./helpers')
const { rocks } = require('./helpers')

test('basic full example on rocks', async function (t) {
const db = HyperDB.rocksdb(await tmp(t), definition)
const db = await rocks(t, definition)

await db.insert('members', { id: 'maf', age: 34 })
await db.insert('members', { id: 'andrew', age: 34 })
await db.insert('members', { id: 'anna', age: 32 })
await db.flush()

{
const result = await collect(db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'maf', age: 34 }
Expand All @@ -25,23 +22,23 @@ test('basic full example on rocks', async function (t) {
await db.insert('members', { id: 'maf', age: 37 })

{
const result = await collect(db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'maf', age: 37 }
])
}

{
const result = await collect(db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }, { reverse: true }))
const result = await db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }, { reverse: true }).toArray()
t.alike(result, [
{ id: 'maf', age: 37 },
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('members'))
const result = await db.find('members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'anna', age: 32 },
Expand All @@ -57,7 +54,7 @@ test('basic full example on rocks', async function (t) {
})

test('delete record', async function (t) {
const db = HyperDB.rocksdb(await tmp(t), definition)
const db = await rocks(t, definition)

await db.insert('members', { id: 'maf', age: 34 })
await db.insert('members', { id: 'andrew', age: 34 })
Expand All @@ -66,14 +63,14 @@ test('delete record', async function (t) {
await db.delete('members', { id: 'maf' })

{
const result = await collect(db.find('members'))
const result = await db.find('members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
Expand All @@ -82,14 +79,14 @@ test('delete record', async function (t) {
await db.flush()

{
const result = await collect(db.find('members'))
const result = await db.find('members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('members/by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
Expand All @@ -102,15 +99,15 @@ test('delete record', async function (t) {
})

test('generated full example on rocks', async function (t) {
const db = HyperDB.rocksdb(await tmp(t), generatedDefinition)
const db = await rocks(t)

await db.insert('@db/members', { id: 'maf', age: 34 })
await db.insert('@db/members', { id: 'andrew', age: 34 })
await db.insert('@db/members', { id: 'anna', age: 32 })
await db.flush()

{
const result = await collect(db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'maf', age: 34 }
Expand All @@ -121,23 +118,23 @@ test('generated full example on rocks', async function (t) {
await db.insert('@db/members', { id: 'maf', age: 37 })

{
const result = await collect(db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'maf', age: 37 }
])
}

{
const result = await collect(db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }, { reverse: true }))
const result = await db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }, { reverse: true }).toArray()
t.alike(result, [
{ id: 'maf', age: 37 },
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('@db/members'))
const result = await db.find('@db/members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 },
{ id: 'anna', age: 32 },
Expand All @@ -153,7 +150,7 @@ test('generated full example on rocks', async function (t) {
})

test('generated delete record', async function (t) {
const db = HyperDB.rocksdb(await tmp(t), generatedDefinition)
const db = await rocks(t)

await db.insert('@db/members', { id: 'maf', age: 34 })
await db.insert('@db/members', { id: 'andrew', age: 34 })
Expand All @@ -162,14 +159,14 @@ test('generated delete record', async function (t) {
await db.delete('@db/members', { id: 'maf' })

{
const result = await collect(db.find('@db/members'))
const result = await db.find('@db/members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
Expand All @@ -178,14 +175,14 @@ test('generated delete record', async function (t) {
await db.flush()

{
const result = await collect(db.find('@db/members'))
const result = await db.find('@db/members').toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
}

{
const result = await collect(db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }))
const result = await db.find('@db/members-by-age', { gte: { age: 33 }, lt: { age: 99 } }).toArray()
t.alike(result, [
{ id: 'andrew', age: 34 }
])
Expand Down
19 changes: 15 additions & 4 deletions test/helpers/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
exports.collect = async function (stream) {
const all = []
for await (const data of stream) all.push(data)
return all
const HyperDB = require('../../')
const tmp = require('test-tmp')

exports.rocks = async function (t, def, opts) {
if (!HyperDB.isDefinition(def)) return exports.rocks(t, require('../fixtures/generated'), def)

const db = HyperDB.rocksdb(await tmp(t), def, opts)
const engine = db.engine

// just to help catch leaks
t.teardown(function () {
if (!engine.closed) throw new Error('Test has a leak, engine did not close')
})

return db
}
47 changes: 47 additions & 0 deletions test/snapshot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
const test = require('brittle')
const { rocks } = require('./helpers')

test('basic snapshot', async function (t) {
const db = await rocks(t)

const empty = db.snapshot()

t.alike(await empty.find('@db/members').toArray(), [])

await db.insert('@db/members', { id: 'someone', age: 40 })

t.alike(await empty.find('@db/members').toArray(), [])
t.alike(await db.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

await db.flush()

t.is(db.updated, false)

t.alike(await empty.find('@db/members').toArray(), [])
t.alike(await db.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

const snap = db.snapshot()

await db.insert('@db/members', { id: 'someone', age: 41 })

t.alike(await empty.find('@db/members').toArray(), [])
t.alike(await db.find('@db/members').toArray(), [{ id: 'someone', age: 41 }])
t.alike(await snap.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

await db.flush()

t.alike(await empty.find('@db/members').toArray(), [])
t.alike(await db.find('@db/members').toArray(), [{ id: 'someone', age: 41 }])
t.alike(await snap.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

await empty.close()

t.alike(await db.find('@db/members').toArray(), [{ id: 'someone', age: 41 }])
t.alike(await snap.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

await db.close()

t.alike(await snap.find('@db/members').toArray(), [{ id: 'someone', age: 40 }])

await snap.close()
})

0 comments on commit 8073ced

Please sign in to comment.