add testSerializationHooks option

pull/23/head
Timothée Rebours 2 years ago
parent c29ec66b37
commit 2a121faccc
  1. 1
      index.d.ts
  2. 5
      lib/datastore.js
  3. 13
      lib/persistence.js
  4. 14
      test/persistence.async.test.js

1
index.d.ts vendored

@ -114,6 +114,7 @@ declare namespace Nedb {
corruptAlertThreshold?: number; corruptAlertThreshold?: number;
compareStrings?(a: string, b: string): number; compareStrings?(a: string, b: string): number;
modes?: {fileMode: number, dirMode: number}; modes?: {fileMode: number, dirMode: number};
testSerializationHooks?: boolean;
} }
interface UpdateOptions { interface UpdateOptions {

@ -193,6 +193,8 @@ class Datastore extends EventEmitter {
* @param {compareStrings} [options.compareStrings] If specified, it overrides default string comparison which is not * @param {compareStrings} [options.compareStrings] If specified, it overrides default string comparison which is not
* well adapted to non-US characters in particular accented letters. Native `localCompare` will most of the time be * well adapted to non-US characters in particular accented letters. Native `localCompare` will most of the time be
* the right choice. * the right choice.
* @param {boolean} [options.testSerializationHooks=true] Whether to test the serialization hooks or not,
* might be CPU-intensive
*/ */
constructor (options) { constructor (options) {
super() super()
@ -262,7 +264,8 @@ class Datastore extends EventEmitter {
afterSerialization: options.afterSerialization, afterSerialization: options.afterSerialization,
beforeDeserialization: options.beforeDeserialization, beforeDeserialization: options.beforeDeserialization,
corruptAlertThreshold: options.corruptAlertThreshold, corruptAlertThreshold: options.corruptAlertThreshold,
modes: options.modes modes: options.modes,
testSerializationHooks: options.testSerializationHooks
}) })
// This new executor is ready if we don't use persistence // This new executor is ready if we don't use persistence

@ -49,6 +49,7 @@ class Persistence {
* @param {object} [options.modes] Modes to use for FS permissions. Will not work on Windows. * @param {object} [options.modes] Modes to use for FS permissions. Will not work on Windows.
* @param {number} [options.modes.fileMode=0o644] Mode to use for files. * @param {number} [options.modes.fileMode=0o644] Mode to use for files.
* @param {number} [options.modes.dirMode=0o755] Mode to use for directories. * @param {number} [options.modes.dirMode=0o755] Mode to use for directories.
* @param {boolean} [options.testSerializationHooks=true] Whether to test the serialization hooks or not, might be CPU-intensive
*/ */
constructor (options) { constructor (options) {
this.db = options.db this.db = options.db
@ -77,11 +78,13 @@ class Persistence {
this.afterSerialization = options.afterSerialization || (s => s) this.afterSerialization = options.afterSerialization || (s => s)
this.beforeDeserialization = options.beforeDeserialization || (s => s) this.beforeDeserialization = options.beforeDeserialization || (s => s)
for (let i = 1; i < 30; i += 1) { if (options.testSerializationHooks === undefined || options.testSerializationHooks) {
for (let j = 0; j < 10; j += 1) { for (let i = 1; i < 30; i += 1) {
const randomString = customUtils.uid(i) for (let j = 0; j < 10; j += 1) {
if (this.beforeDeserialization(this.afterSerialization(randomString)) !== randomString) { const randomString = customUtils.uid(i)
throw new Error('beforeDeserialization is not the reverse of afterSerialization, cautiously refusing to start NeDB to prevent dataloss') if (this.beforeDeserialization(this.afterSerialization(randomString)) !== randomString) {
throw new Error('beforeDeserialization is not the reverse of afterSerialization, cautiously refusing to start NeDB to prevent dataloss')
}
} }
} }
} }

@ -461,6 +461,20 @@ describe('Persistence async', function () {
assert.equal(await fs.readFile(hookTestFilename, 'utf8'), 'Some content') assert.equal(await fs.readFile(hookTestFilename, 'utf8'), 'Some content')
}) })
it('Declaring two hooks that are not reverse of one another will not cause exception if options.testSerializationHooks === false', async () => {
const hookTestFilename = 'workspace/hookTest.db'
await storage.ensureFileDoesntExistAsync(hookTestFilename)
await fs.writeFile(hookTestFilename, 'Some content', 'utf8')
const db = new Datastore({
filename: hookTestFilename,
autoload: true,
afterSerialization: as,
beforeDeserialization: function (s) { return s },
testSerializationHooks: false
})
await assert.rejects(() => db.autoloadPromise)
})
it('A serialization hook can be used to transform data before writing new state to disk', async () => { it('A serialization hook can be used to transform data before writing new state to disk', async () => {
const hookTestFilename = 'workspace/hookTest.db' const hookTestFilename = 'workspace/hookTest.db'
await storage.ensureFileDoesntExistAsync(hookTestFilename) await storage.ensureFileDoesntExistAsync(hookTestFilename)

Loading…
Cancel
Save