var should = require('chai').should() , assert = require('chai').assert , testDb = 'workspace/test.db' , fs = require('fs') , path = require('path') , _ = require('underscore') , async = require('async') , model = require('../lib/model') , Datastore = require('../lib/datastore') , Persistence = require('../lib/persistence') ; // Test that even if a callback throws an exception, the next DB operations will still be executed // We prevent Mocha from catching the exception we throw on purpose by remembering all current handlers, remove them and register them back after test ends function testThrowInCallback (d, done) { var currentUncaughtExceptionHandlers = process.listeners('uncaughtException'); process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function (err) { // Do nothing with the error which is only there to test we stay on track }); d.find({}, function (err) { process.nextTick(function () { d.insert({ bar: 1 }, function (err) { process.removeAllListeners('uncaughtException'); for (var i = 0; i < currentUncaughtExceptionHandlers.length; i += 1) { process.on('uncaughtException', currentUncaughtExceptionHandlers[i]); } done(); }); }); throw new Error('Some error'); }); } // Test that if the callback is falsy, the next DB operations will still be executed function testFalsyCallback (d, done) { d.insert({ a: 1 }, null); process.nextTick(function () { d.update({ a: 1 }, { a: 2 }, {}, null); process.nextTick(function () { d.update({ a: 2 }, { a: 1 }, null); process.nextTick(function () { d.remove({ a: 2 }, {}, null); process.nextTick(function () { d.remove({ a: 2 }, null); process.nextTick(function () { d.find({}, done); }); }); }); }); }); } // Test that operations are executed in the right order // We prevent Mocha from catching the exception we throw on purpose by remembering all current handlers, remove them and register them back after test ends function testRightOrder (d, done) { var currentUncaughtExceptionHandlers = process.listeners('uncaughtException'); process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function (err) { // Do nothing with the error which is only there to test we stay on track }); d.find({}, function (err, docs) { docs.length.should.equal(0); d.insert({ a: 1 }, function () { d.update({ a: 1 }, { a: 2 }, {}, function () { d.find({}, function (err, docs) { docs[0].a.should.equal(2); process.nextTick(function () { d.update({ a: 2 }, { a: 3 }, {}, function () { d.find({}, function (err, docs) { docs[0].a.should.equal(3); process.removeAllListeners('uncaughtException'); for (var i = 0; i < currentUncaughtExceptionHandlers.length; i += 1) { process.on('uncaughtException', currentUncaughtExceptionHandlers[i]); } done(); }); }); }); throw new Error('Some error'); }); }); }); }); } // Note: The following test does not have any assertion because it // is meant to address the deprecation warning: // (node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral. // see var testEventLoopStarvation = function(d, done){ var times = 1001; var i = 0; while ( i