diff --git a/lib/persistence.js b/lib/persistence.js index a0bb089..1886000 100644 --- a/lib/persistence.js +++ b/lib/persistence.js @@ -21,6 +21,8 @@ var storage = require('./storage') * Node Webkit stores application data such as cookies and local storage (the best place to store data in my opinion) */ function Persistence (options) { + var i, j, randomString; + this.db = options.db; this.inMemoryOnly = this.db.inMemoryOnly; this.filename = this.db.filename; @@ -36,14 +38,22 @@ function Persistence (options) { // After serialization and before deserialization hooks with some basic sanity checks if (options.afterSerialization && !options.beforeDeserialization) { - throw "Serialization hook defined but deserialization hook undefined, cautiously refusing to start NeDB"; + throw "Serialization hook defined but deserialization hook undefined, cautiously refusing to start NeDB to prevent dataloss"; } if (!options.afterSerialization && options.beforeDeserialization) { - throw "Serialization hook undefined but deserialization hook defined, cautiously refusing to start NeDB"; + throw "Serialization hook undefined but deserialization hook defined, cautiously refusing to start NeDB to prevent dataloss"; } this.afterSerialization = options.afterSerialization || function (s) { return s; }; this.beforeDeserialization = options.beforeDeserialization || function (s) { return s; }; - + for (i = 1; i < 30; i += 1) { + for (j = 0; j < 10; j += 1) { + randomString = customUtils.uid(i); + if (this.beforeDeserialization(this.afterSerialization(randomString)) !== randomString) { + throw "beforeDeserialization is not the reverse of afterSerialization, cautiously refusing to start NeDB to prevent dataloss"; + } + } + } + // For NW apps, store data in the same directory where NW stores application data if (this.filename && options.nodeWebkitAppName) { console.log("=================================================================="); diff --git a/test/persistence.test.js b/test/persistence.test.js index d6d7007..9e6e738 100644 --- a/test/persistence.test.js +++ b/test/persistence.test.js @@ -275,20 +275,48 @@ describe('Persistence', function () { it("Declaring only one hook will throw an exception to prevent data loss", function (done) { var hookTestFilename = 'workspace/hookTest.db' Persistence.ensureFileDoesntExist(hookTestFilename, function () { + fs.writeFileSync(hookTestFilename, "Some content", "utf8"); + (function () { new Datastore({ filename: hookTestFilename, autoload: true , afterSerialization: as }); }).should.throw(); + // Data file left untouched + fs.readFileSync(hookTestFilename, "utf8").should.equal("Some content"); + (function () { new Datastore({ filename: hookTestFilename, autoload: true , beforeDeserialization: bd }); }).should.throw(); + // Data file left untouched + fs.readFileSync(hookTestFilename, "utf8").should.equal("Some content"); + + done(); + }); + }); + + it("Declaring two hooks that are not reverse of one another will cause an exception to prevent data loss", function (done) { + var hookTestFilename = 'workspace/hookTest.db' + Persistence.ensureFileDoesntExist(hookTestFilename, function () { + fs.writeFileSync(hookTestFilename, "Some content", "utf8"); + + (function () { + new Datastore({ filename: hookTestFilename, autoload: true + , afterSerialization: as + , beforeDeserialization: function (s) { return s; } + }); + }).should.throw(); + + // Data file left untouched + fs.readFileSync(hookTestFilename, "utf8").should.equal("Some content"); + done(); }); + }); it("A serialization hook can be used to transform data before writing new state to disk", function (done) {