UNPKG

medea

Version:

A lightweight key-value storage library.

365 lines (311 loc) 10 kB
var assert = require('assert'); var fs = require('fs'); var path = require('path'); var medea = require('../'); var rimraf = require('rimraf'); var root = __dirname + '/tmp/medea_compact_test'; var setup = function (done) { require('rimraf')(directory, done); }; describe('Medea#compact', function() { // disable timeout this.timeout(0); describe('Multiple time overwriting same key', function () { it('successfully overwites same key', function (done) { var directory = root + 'overwrites_same_key'; var db = medea({ maxFileSize: 512 }); var test = function (index) { if (index === 50) { db.close(function() { fs.readdirSync(directory).forEach(function (filename) { filename = directory + '/' + filename; try { var stat = fs.statSync(filename) assert(stat.size < db.maxFileSize); } catch(e) { if (e.code !== 'EPERM') { // issues/51 throw e; } } }); done(); }); return; } var buffer1 = new Buffer(50), buffer2 = new Buffer(50), buffer3 = new Buffer(50); buffer1.fill(1); buffer2.fill(2); buffer3.fill(3); db.put('foo1', buffer1, function (err) { if (err) return done(err); db.put('foo1', buffer2, function (err) { if (err) return done(err); db.put('foo1', buffer3, function (err) { if (err) return done(err); db.compact(function (err) { if (err) return done(err) db.compact(function (err) { if (err) return done(err) db.get('foo1', function (err, value) { assert.deepEqual(value, buffer3); test(++index); }) }); }); }); }); }); } db.open(directory, function() { test(0); }); }); }); describe('Multiple time writing different keys', function () { it('successfully writing different key', function (done) { var db = medea({ maxFileSize: 512 }); var directory = root + 'writes_different_key'; var test = function (index) { if (index === 50) { db.close(function() { fs.readdirSync(directory).forEach(function (filename) { filename = directory + '/' + filename; try { var stat = fs.statSync(filename) assert(stat.size < db.maxFileSize); } catch(e) { if (e.code !== 'EPERM') { // issues/51 throw e; } } }); done(); }); return; } var buffer1 = new Buffer(50), buffer2 = new Buffer(50), buffer3 = new Buffer(50); buffer1.fill(1); buffer2.fill(2); buffer3.fill(3); db.put('foo1', buffer1, function (err) { if (err) return done(err); db.put('foo2', buffer2, function (err) { if (err) return done(err); db.put('foo3', buffer3, function (err) { if (err) return done(err); db.compact(function (err) { if (err) return done(err) db.compact(function (err) { if (err) return done(err) db.get('foo1', function (err, value) { assert.deepEqual(value, buffer1); db.get('foo2', function (err, value) { assert.deepEqual(value, buffer2); db.get('foo3', function (err, value) { assert.deepEqual(value, buffer3); test(++index); }); }); }) }); }); }); }); }); } db.open(directory, function() { test(0); }); }); }); describe('Write large amount of data', function () { var max = 100, bufferLength = 100; var db = medea({ maxFileSize: 512 }); var directory = root + 'large_amounts'; before(function (done) { rimraf(directory, function() { db.open(directory, function() { var put = function(index) { if (index === max) { return done(); } var buffer = new Buffer(bufferLength); buffer.fill(index); db.put(buffer, buffer, function(err) { if (err) return done(err); put(++index); }); } put(0); }); }); }); it('successfully compacts', function (done) { db.compact(function (err) { if (err) return done(err); db.compact(function (err) { if (err) return done(err); done() }); }); }); it('successfully saves data', function (done) { var get = function (index) { if (index === max) { return done(); } var buffer = new Buffer(bufferLength); buffer.fill(index); db.get(buffer, function (err, value) { if (err) return done(err); assert.deepEqual(value, buffer); get(++index); }); } get(0); }); it('obeys maxFileSize', function () { fs.readdirSync(directory).forEach(function (filename) { filename = directory + '/' + filename; try { var stat = fs.statSync(filename) assert(stat.size < db.maxFileSize); } catch(e) { if (e.code !== 'EPERM') { // issues/51 throw e; } } }); }); }); describe('write many keys', function () { var db = medea({ maxFileSize: 1024 * 1024 }); var directory = root + 'many_keys'; var max = 25000; before(function (done) { require('rimraf')(directory, function () { db.open(directory, function() { var put = function(index) { if (index === max) { return done(); } db.put(index.toString(), index.toString(), function(err) { if (err) return done(err); put(++index); }); } put(0); }); }); }); it('successfully compacts', function (done) { db.compact(function (err) { if (err) return done(err); db.compact(function (err) { if (err) return done(err); done() }); }); }); it('successfully saves data', function (done) { var get = function (index) { if (index === max) { return done(); } db.get(index.toString(), function (err, value) { if (err) return done(err); assert.deepEqual(value.toString(), index.toString()); get(++index); }); } get(0); }); it('obeys maxFileSize', function () { fs.readdirSync(directory).forEach(function (filename) { filename = directory + '/' + filename; var stat = fs.statSync(filename) assert(stat.size < db.maxFileSize); }); }); }) describe('handle missing hint files', function () { it('should pass', function(done) { var directory = root; var db1 = medea({}); require('rimraf')(directory, function() { db1.open(directory, function(err) { assert(!err); db1.put('hello', 'world', function(err) { assert(!err); db1.close(function(err) { assert(!err); rimraf(directory + '/1.medea.hint', function() { var db2 = medea({}); db2.open(directory, function(err) { assert(!err); db2.compact(function(err) { if (err) { throw err; } done(); }) }); }); }); }); }); }); }); }); describe('cleanup dangling hint files', function () { it('should pass', function(done) { var directory = root; var db1 = medea({}); require('rimraf')(directory, function() { db1.open(directory, function(err) { assert(!err); db1.put('hello', 'world', function(err) { assert(!err); db1.close(function(err) { var db2 = medea({}); db2.open(directory, function(err) { assert(!err); if (process.platform !== 'win32') { // prevent windows from erroring due to in-progress I/O completion state. var fds = []; for (var i = 10; i < 15; i++) { var fd = fs.openSync(path.join(directory, i + '.medea.hint'), 'w'); fds.push(fd); } fds.forEach(function(fd) { fs.closeSync(fd); }); var files = fs.readdirSync(directory); assert.equal(files.length, 10); } db2.compact(function(err) { assert(!err); var files = fs.readdirSync(directory); var hintFileNumbers = files.filter(function(file) { return file.indexOf('hint') > -1; }).map(function(file) { return file[0]; }); hintFileNumbers.forEach(function(number) { assert(files.indexOf(number + '.medea.data') > -1); }); done(); }); }); }); }); }); }); }); }); });