diff --git a/lib/datastore.js b/lib/datastore.js index 9f9b185..32a8f6a 100755 --- a/lib/datastore.js +++ b/lib/datastore.js @@ -342,8 +342,8 @@ class Datastore extends EventEmitter { */ setAutocompactionInterval (interval) { const minInterval = 5000 - if (typeof interval !== 'number') throw new Error('Interval must be a number') - const realInterval = Math.max(interval || 0, minInterval) + if (Number.isNaN(Number(interval))) throw new Error('Interval must be a non-NaN number') + const realInterval = Math.max(Number(interval) || 0, minInterval) this.stopAutocompaction() diff --git a/test/persistence.async.test.js b/test/persistence.async.test.js index c02df3b..c414a36 100755 --- a/test/persistence.async.test.js +++ b/test/persistence.async.test.js @@ -12,6 +12,7 @@ const { execFile, fork } = require('child_process') const { promisify } = require('util') const { ensureFileDoesntExistAsync } = require('../lib/storage') const { once } = require('events') +const { wait } = require('./utils.test') const Readable = require('stream').Readable describe('Persistence async', function () { @@ -346,13 +347,11 @@ describe('Persistence async', function () { // Default corruptAlertThreshold d = new Datastore({ filename: corruptTestFilename }) - await assert.rejects(() => d.loadDatabaseAsync(), err => { - assert.notEqual(err, undefined) - assert.notEqual(err, null) - assert.equal(err.corruptionRate, 0.25) - assert.equal(err.corruptItems, 1) - assert.equal(err.dataLength, 4) - return true + await assert.rejects(() => d.loadDatabaseAsync(), { + corruptionRate: 0.25, + corruptItems: 1, + dataLength: 4, + message: '25% of the data file is corrupt, more than given corruptAlertThreshold (10%). Cautiously refusing to start NeDB to prevent dataloss.' }) await fs.writeFile(corruptTestFilename, fakeData, 'utf8') @@ -360,13 +359,11 @@ describe('Persistence async', function () { await d.loadDatabaseAsync() await fs.writeFile(corruptTestFilename, fakeData, 'utf8') d = new Datastore({ filename: corruptTestFilename, corruptAlertThreshold: 0 }) - await assert.rejects(() => d.loadDatabaseAsync(), err => { - assert.notEqual(err, undefined) - assert.notEqual(err, null) - assert.equal(err.corruptionRate, 0.25) - assert.equal(err.corruptItems, 1) - assert.equal(err.dataLength, 4) - return true + await assert.rejects(() => d.loadDatabaseAsync(), { + corruptionRate: 0.25, + corruptItems: 1, + dataLength: 4, + message: '25% of the data file is corrupt, more than given corruptAlertThreshold (0%). Cautiously refusing to start NeDB to prevent dataloss.' }) }) @@ -380,6 +377,41 @@ describe('Persistence async', function () { await compacted // should already be resolved when the function returns, but still awaiting for it }) + it('setAutocompaction fails gracefully when passed a NaN', async () => { + assert.throws(() => { + d.setAutocompactionInterval(Number.NaN) + }, { + message: 'Interval must be a non-NaN number' + }) + }) + + it('setAutocompaction fails gracefully when passed a string non castable to a number', async () => { + assert.throws(() => { + d.setAutocompactionInterval('a') + }, { + message: 'Interval must be a non-NaN number' + }) + }) + + it('setAutocompaction works if passed a number castable to a number below 5000ms', async () => { + let i = 0 + const backup = d.compactDatafile + d.compactDatafile = () => { + backup.call(d) + i++ + } + try { + d.setAutocompactionInterval('0') // it should set the actual interval to 5000 + await wait(6000) + assert.ok(i < 3) + assert.ok(i >= 1) + } finally { + d.compactDatafile = backup + d.stopAutocompaction() + assert.equal(d._autocompactionIntervalId, null) + } + }) + describe('Serialization hooks', async () => { const as = s => `before_${s}_after` const bd = s => s.substring(7, s.length - 6)