Skip to content

Commit

Permalink
🥅 improve error handling for decode failures, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ctcpip committed May 9, 2024
1 parent a39c4c7 commit bdd29a9
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 11 deletions.
11 changes: 10 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,16 @@ module.exports = function (Adapter) {
if (error)
return error.code === 'ENOENT' ? resolve() : reject(error)

record = msgpack.decode(buffer)
if(buffer.length === 0) {
return reject(new Error(`Decode record failed. File is empty: ${filePath}`))
}
else {
try {
record = msgpack.decode(buffer)
} catch (e) {
return reject(new Error(`Decode record failed. File is corrupt: ${filePath}`, { cause: e }))
}
}

if (!(type in self.db)) self.db[type] = {}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint": "eslint index.js",
"postpublish": "npm run tag",
"tag": "git tag `npm v fortune-fs version` && git push origin --tags",
"test": "npm run lint && node test.js"
"test": "npm run lint && node test/test.js"
},
"dependencies": {
"lockfile": "^1.0.4",
Expand Down
1 change: 1 addition & 0 deletions test/corrupt-file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��id�bar
Empty file added test/empty-file
Empty file.
81 changes: 72 additions & 9 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,85 @@
'use strict'

var testAdapter = require('fortune/test/adapter')
var fsAdapter = require('./index')
var fsAdapter = require('../index')
const fortune = require('fortune')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const run = require('tapdance')

testAdapter(fsAdapter)

assert.doesNotThrow(() => {
run((assert, comment) => {
comment('concurrentReads validation')

const concurrentReads = 1

const store = fortune({}, {
adapter: [fsAdapter, { concurrentReads }],
})
assert.equal(store.adapter.options.concurrentReads, concurrentReads)
})

assert.throws(() => {
fortune({}, {
adapter: [fsAdapter, { concurrentReads: 0 }],
assert(store.adapter.options.concurrentReads === concurrentReads, `adapter has expected concurrentReads value --- expected: ${store.adapter.options.concurrentReads} --- actual: ${concurrentReads}`)

let thrown = false
let expectedError

try {
fortune({}, {
adapter: [fsAdapter, { concurrentReads: 0 }],
})
} catch (e) {
thrown = true
expectedError = e.message === 'concurrentReads must be > 0'
if(!expectedError) {
// only log the error if it was something we did not expect
console.error(e)
}
}

assert(thrown, 'concurrentReads 0 is not valid')
assert(expectedError, 'got expected error for concurrentReads 0')
});

(async () => {

run(async (assert, comment) => {
comment('msgpack decode validation')

const type = 'foo'
const schema = {}
schema[type] = { bar: Boolean }

const store = fortune(
schema,
{ adapter: [fsAdapter] })

fs.mkdirSync(`db/${type}`, { recursive: true })
fs.copyFileSync('test/empty-file', `db/${type}/1`)
fs.copyFileSync('test/valid-file', `db/${type}/3`)
fs.copyFileSync('test/corrupt-file', `db/${type}/6`)

let error = null

try {
await store.find(type, [1])
} catch (e) {
error = e
}

assert(error.message.includes('Decode record failed. File is empty'), `empty error message is present: ${error.message}`)

error = null

try {
await store.find(type, [6])
} catch (e) {
error = e
}

assert(error.message.includes('Decode record failed. File is corrupt'), `corrupt error message is present ${error.message}`)

const result = await store.find(type, [3])
assert(result.payload.records.length === 1, 'valid record is found')

})
})

})()
1 change: 1 addition & 0 deletions test/valid-file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
��id�bar�

0 comments on commit bdd29a9

Please sign in to comment.