mirror of https://github.com/seald/nedb
parent
46c4723fc5
commit
4058b23ddb
@ -0,0 +1,280 @@ |
||||
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') |
||||
; |
||||
|
||||
|
||||
describe('Persistence', function () { |
||||
var d; |
||||
|
||||
beforeEach(function (done) { |
||||
d = new Datastore({ filename: testDb }); |
||||
d.filename.should.equal(testDb); |
||||
d.inMemoryOnly.should.equal(false); |
||||
|
||||
async.waterfall([ |
||||
function (cb) { |
||||
Persistence.ensureDirectoryExists(path.dirname(testDb), function () { |
||||
fs.exists(testDb, function (exists) { |
||||
if (exists) { |
||||
fs.unlink(testDb, cb); |
||||
} else { return cb(); } |
||||
}); |
||||
}); |
||||
} |
||||
, function (cb) { |
||||
d.loadDatabase(function (err) { |
||||
assert.isNull(err); |
||||
d.datafileSize.should.equal(0); |
||||
d.getAllData().length.should.equal(0); |
||||
return cb(); |
||||
}); |
||||
} |
||||
], done); |
||||
}); |
||||
|
||||
it('Every line represents a document', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", hello: 'world' }) + '\n' + |
||||
model.serialize({ _id: "3", nested: { today: now } }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(3); |
||||
_.isEqual(treatedData[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "2", hello: 'world' }).should.equal(true); |
||||
_.isEqual(treatedData[2], { _id: "3", nested: { today: now } }).should.equal(true); |
||||
}); |
||||
|
||||
it('Badly formatted lines have no impact on the treated data', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
'garbage\n' + |
||||
model.serialize({ _id: "3", nested: { today: now } }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(2); |
||||
_.isEqual(treatedData[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "3", nested: { today: now } }).should.equal(true); |
||||
}); |
||||
|
||||
it('Well formatted lines that have no _id are not included in the data', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", hello: 'world' }) + '\n' + |
||||
model.serialize({ nested: { today: now } }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(2); |
||||
_.isEqual(treatedData[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "2", hello: 'world' }).should.equal(true); |
||||
}); |
||||
|
||||
it('If two lines concern the same doc (= same _id), the last one is the good version', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", hello: 'world' }) + '\n' + |
||||
model.serialize({ _id: "1", nested: { today: now } }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(2); |
||||
_.isEqual(treatedData[0], { _id: "1", nested: { today: now } }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "2", hello: 'world' }).should.equal(true); |
||||
}); |
||||
|
||||
it('If a doc contains $$deleted: true, that means we need to remove it from the data', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", hello: 'world' }) + '\n' + |
||||
model.serialize({ _id: "1", $$deleted: true }) + '\n' + |
||||
model.serialize({ _id: "3", today: now }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(2); |
||||
_.isEqual(treatedData[0], { _id: "2", hello: 'world' }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "3", today: now }).should.equal(true); |
||||
}); |
||||
|
||||
it('If a doc contains $$deleted: true, no error is thrown if the doc wasnt in the list before', function () { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", $$deleted: true }) + '\n' + |
||||
model.serialize({ _id: "3", today: now }) |
||||
, treatedData = Persistence.treatRawData(rawData) |
||||
; |
||||
|
||||
treatedData.sort(function (a, b) { return a._id - b._id; }); |
||||
treatedData.length.should.equal(2); |
||||
_.isEqual(treatedData[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); |
||||
_.isEqual(treatedData[1], { _id: "3", today: now }).should.equal(true); |
||||
}); |
||||
|
||||
it('Compact database on load', function (done) { |
||||
d.insert({ a: 2 }, function () { |
||||
d.insert({ a: 4 }, function () { |
||||
d.remove({ a: 2 }, {}, function () { |
||||
// Here, the underlying file is 3 lines long for only one document
|
||||
var data = fs.readFileSync(d.filename, 'utf8').split('\n') |
||||
, filledCount = 0; |
||||
|
||||
data.forEach(function (item) { if (item.length > 0) { filledCount += 1; } }); |
||||
filledCount.should.equal(3); |
||||
|
||||
d.loadDatabase(function (err) { |
||||
assert.isNull(err); |
||||
|
||||
// Now, the file has been compacted and is only 1 line long
|
||||
var data = fs.readFileSync(d.filename, 'utf8').split('\n') |
||||
, filledCount = 0; |
||||
|
||||
data.forEach(function (item) { if (item.length > 0) { filledCount += 1; } }); |
||||
filledCount.should.equal(1); |
||||
|
||||
done(); |
||||
}); |
||||
}) |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
it('datafileSize is the size of the dataset upon a databaseLoad', function (done) { |
||||
var now = new Date() |
||||
, rawData = model.serialize({ _id: "1", a: 2, ages: [1, 5, 12] }) + '\n' + |
||||
model.serialize({ _id: "2", hello: 'world' }) + '\n' + |
||||
model.serialize({ _id: "3", nested: { today: now } }) |
||||
; |
||||
|
||||
d.getAllData().length.should.equal(0); |
||||
d.datafileSize.should.equal(0); |
||||
|
||||
fs.writeFile(testDb, rawData, 'utf8', function () { |
||||
d.loadDatabase(function () { |
||||
d.getAllData().length.should.equal(3); |
||||
d.datafileSize.should.equal(3); |
||||
|
||||
d.find({}, function (err, docs) { |
||||
docs.sort(function (a, b) { return a._id - b._id; }); |
||||
docs.length.should.equal(3); |
||||
_.isEqual(docs[0], { _id: "1", a: 2, ages: [1, 5, 12] }).should.equal(true); |
||||
_.isEqual(docs[1], { _id: "2", hello: 'world' }).should.equal(true); |
||||
_.isEqual(docs[2], { _id: "3", nested: { today: now } }).should.equal(true); |
||||
|
||||
done(); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
it('Calling loadDatabase after the data was modified doesnt change its contents', function (done) { |
||||
d.loadDatabase(function () { |
||||
d.insert({ a: 1 }, function (err) { |
||||
assert.isNull(err); |
||||
d.insert({ a: 2 }, function (err) { |
||||
var data = d.getAllData() |
||||
, doc1 = _.find(data, function (doc) { return doc.a === 1; }) |
||||
, doc2 = _.find(data, function (doc) { return doc.a === 2; }) |
||||
; |
||||
assert.isNull(err); |
||||
data.length.should.equal(2); |
||||
doc1.a.should.equal(1); |
||||
doc2.a.should.equal(2); |
||||
|
||||
d.loadDatabase(function (err) { |
||||
var data = d.getAllData() |
||||
, doc1 = _.find(data, function (doc) { return doc.a === 1; }) |
||||
, doc2 = _.find(data, function (doc) { return doc.a === 2; }) |
||||
; |
||||
assert.isNull(err); |
||||
data.length.should.equal(2); |
||||
doc1.a.should.equal(1); |
||||
doc2.a.should.equal(2); |
||||
|
||||
done(); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
it('Calling loadDatabase after the datafile was removed will reset the database', function (done) { |
||||
d.loadDatabase(function () { |
||||
d.insert({ a: 1 }, function (err) { |
||||
assert.isNull(err); |
||||
d.insert({ a: 2 }, function (err) { |
||||
var data = d.getAllData() |
||||
, doc1 = _.find(data, function (doc) { return doc.a === 1; }) |
||||
, doc2 = _.find(data, function (doc) { return doc.a === 2; }) |
||||
; |
||||
assert.isNull(err); |
||||
data.length.should.equal(2); |
||||
doc1.a.should.equal(1); |
||||
doc2.a.should.equal(2); |
||||
|
||||
fs.unlink(testDb, function (err) { |
||||
assert.isNull(err); |
||||
d.loadDatabase(function (err) { |
||||
assert.isNull(err); |
||||
d.getAllData().length.should.equal(0); |
||||
|
||||
done(); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
it('Calling loadDatabase after the datafile was modified loads the new data', function (done) { |
||||
d.loadDatabase(function () { |
||||
d.insert({ a: 1 }, function (err) { |
||||
assert.isNull(err); |
||||
d.insert({ a: 2 }, function (err) { |
||||
var data = d.getAllData() |
||||
, doc1 = _.find(data, function (doc) { return doc.a === 1; }) |
||||
, doc2 = _.find(data, function (doc) { return doc.a === 2; }) |
||||
; |
||||
assert.isNull(err); |
||||
data.length.should.equal(2); |
||||
doc1.a.should.equal(1); |
||||
doc2.a.should.equal(2); |
||||
|
||||
fs.writeFile(testDb, '{"a":3,"_id":"aaa"}', 'utf8', function (err) { |
||||
assert.isNull(err); |
||||
d.loadDatabase(function (err) { |
||||
var data = d.getAllData() |
||||
, doc1 = _.find(data, function (doc) { return doc.a === 1; }) |
||||
, doc2 = _.find(data, function (doc) { return doc.a === 2; }) |
||||
, doc3 = _.find(data, function (doc) { return doc.a === 3; }) |
||||
; |
||||
assert.isNull(err); |
||||
data.length.should.equal(1); |
||||
doc3.a.should.equal(3); |
||||
assert.isUndefined(doc1); |
||||
assert.isUndefined(doc2); |
||||
|
||||
done(); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
}); |
||||
|
||||
}); |
Loading…
Reference in new issue