[Pkg-javascript-commits] [dirty.js] 01/02: Imported Upstream version 1.0.0
Gianfranco Costamagna
locutusofborg at moszumanska.debian.org
Tue May 16 08:56:17 UTC 2017
This is an automated email from the git hooks/post-receive script.
locutusofborg pushed a commit to branch master
in repository dirty.js.
commit 4e70d21f517e587072c69b767e3c85ee108a21f4
Author: Gianfranco Costamagna <costamagnagianfranco at yahoo.it>
Date: Tue May 16 10:56:13 2017 +0200
Imported Upstream version 1.0.0
---
.gitignore | 2 +-
.travis.yml | 4 +
Makefile | 2 +-
README.md | 75 ++++--
benchmark/dirty/for-each.js | 9 +-
benchmark/dirty/get.js | 8 +-
benchmark/dirty/load.js | 10 +-
benchmark/dirty/set-drain-256-bytes-per-doc.js | 8 +-
benchmark/dirty/set-drain.js | 8 +-
benchmark/dirty/set.js | 10 +-
lib/dirty/dirty.js | 86 ++++++-
package.json | 10 +-
test/common.js | 17 --
test/config.js | 14 ++
test/nostore/test-load-event.js | 13 -
test/nostore/test-set-callback.js | 13 -
test/simple/test-dirty.js | 330 -------------------------
test/system/test-flush.js | 12 -
test/system/test-for-each.js | 15 --
test/system/test-load.js | 29 ---
test/system/test-size.js | 8 -
test/test-api.js | 158 ++++++++++++
test/test-nostore.js | 31 +++
test/test-system.js | 118 +++++++++
test/test-types.js | 19 ++
test/tmp/.empty | 0
test/undefined-key.js | 19 ++
27 files changed, 530 insertions(+), 498 deletions(-)
diff --git a/.gitignore b/.gitignore
index 2d2a01c..288d75b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
*.dirty
-node_modules
\ No newline at end of file
+node_modules
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e89e59d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: node_js
+node_js:
+ - "0.10"
+ - "0.8"
diff --git a/Makefile b/Makefile
index af75876..795a031 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
test:
- @find test/{simple,system}/test-*.js | xargs -n 1 -t node
+ npm test
benchmark-v8:
@find benchmark/v8/*.js | xargs -n 1 -t node
diff --git a/README.md b/README.md
index dcd3baf..4e275db 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,9 @@ A tiny & fast key value store with append-only disk log. Ideal for apps with < 1
## Installation
- npm install dirty
+```bash
+npm install dirty
+```
## Why dirty?
@@ -21,26 +23,27 @@ but it is a wonderful solution for anything smaller than that.
## Tutorial
- require('../test/common');
- var db = require('dirty')('user.db');
+```javascript
+ var dirty = require('dirty');
+ var db = dirty('user.db');
- db.on('load', function() {
- db.set('john', {eyes: 'blue'});
- console.log('Added john, he has %s eyes.', db.get('john').eyes);
+ db.on('load', function() {
+ db.set('john', {eyes: 'blue'});
+ console.log('Added john, he has %s eyes.', db.get('john').eyes);
- db.set('bob', {eyes: 'brown'}, function() {
- console.log('User bob is now saved on disk.')
- });
-
- db.forEach(function(key, val) {
- console.log('Found key: %s, val: %j', key, val);
- });
+ db.set('bob', {eyes: 'brown'}, function() {
+ console.log('User bob is now saved on disk.')
});
- db.on('drain', function() {
- console.log('All records are saved on disk now.');
+ db.forEach(function(key, val) {
+ console.log('Found key: %s, val: %j', key, val);
});
+ });
+ db.on('drain', function() {
+ console.log('All records are saved on disk now.');
+ });
+```
Output:
Added john, he has blue eyes.
@@ -58,11 +61,12 @@ can also omit the `path` if you don't want disk persistence (useful for testing)
The constructor can be invoked in multiple ways:
- require('dirty')('my.db');
- require('dirty').Dirty('my.db');
- new (require('dirty'))('my.db');
- new (require('dirty').Dirty)('my.db');
-
+```javascript
+require('dirty')('my.db');
+require('dirty').Dirty('my.db');
+new (require('dirty'))('my.db');
+new (require('dirty').Dirty)('my.db');
+```
### dirty.path
The path of the dirty database.
@@ -91,6 +95,10 @@ if you are only interested in a limited number of records).
This function is blocking and runs at ~4 Mhz.
+### dirty.close()
+
+Close the dirty db file handle.
+
### dirty event: 'load' (length)
Emitted once the database file has finished loading. It is not safe to access
@@ -99,10 +107,37 @@ records before this event fires. Writing records however should be fine.
`length` is the amount of records the database is holding. This only counts each
key once, even if it had been overwritten.
+You can chain the on load to the contructor as follows:
+
+```javascript
+var db = dirty(file).on('load', function() { ... });
+```
+
### dirty event: 'drain' ()
Emitted whenever all records have been written to disk.
+### dirty event: 'read_close' ()
+
+Emitted once the database file read stream closed.
+
+### dirty event : 'write_close' ()
+
+Emitted once the database file write stream closed.
+
+## Tests
+
+[![Build Status](https://travis-ci.org/felixge/node-dirty.png)](https://travis-ci.org/felixge/node-dirty)
+
+Dirty utilizes the [Mocha](http://visionmedia.github.com/mocha/) test framework.
+
+```bash
+git clone https://github.com/felixge/node-dirty
+cd node-dirty
+npm install
+npm test
+```
+
## License
node-dirty is licensed under the MIT license.
diff --git a/benchmark/dirty/for-each.js b/benchmark/dirty/for-each.js
index 29fd4d1..7a088ab 100644
--- a/benchmark/dirty/for-each.js
+++ b/benchmark/dirty/for-each.js
@@ -1,23 +1,22 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e6,
- dirty = require('dirty')(),
+ dirty = require(config.LIB_DIRTY)(),
util = require('util');
for (var i = 0; i < COUNT; i++) {
dirty.set(i, i);
}
-var start = +new Date, i = 0;
+var start = Date.now(), i = 0;
dirty.forEach(function(key, doc) {
if (!key && key !== 0) {
throw new Error('implementation fail');
}
});
-var ms = +new Date - start,
+var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2),
million = COUNT / 1e6;
// Can't use console.log() since since I also test this in ancient node versions
util.log(mhz+' Mhz ('+million+' million in '+ms+' ms)');
-
diff --git a/benchmark/dirty/get.js b/benchmark/dirty/get.js
index 50722f9..c5e6db7 100644
--- a/benchmark/dirty/get.js
+++ b/benchmark/dirty/get.js
@@ -1,20 +1,20 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e6,
- dirty = require('dirty')(),
+ dirty = require(config.LIB_DIRTY)(),
util = require('util');
for (var i = 0; i < COUNT; i++) {
dirty.set(i, i);
}
-var start = +new Date;
+var start = Date.now();
for (var i = 0; i < COUNT; i++) {
if (dirty.get(i) !== i) {
throw new Error('implementation fail');
}
}
-var ms = +new Date - start,
+var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2),
million = COUNT / 1e6;
diff --git a/benchmark/dirty/load.js b/benchmark/dirty/load.js
index 01fc24d..6d0359a 100644
--- a/benchmark/dirty/load.js
+++ b/benchmark/dirty/load.js
@@ -1,7 +1,7 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e4,
- DB_FILE = __dirname+'/../../test/tmp/benchmark-set-drain.dirty',
- dirty = require('dirty')(DB_FILE),
+ DB_FILE = config.TMP_PATH + '/benchmark-set-drain.dirty',
+ dirty = require(config.LIB_DIRTY)(DB_FILE),
util = require('util'),
loaded = false;
@@ -10,9 +10,9 @@ for (var i = 0; i < COUNT; i++) {
}
dirty.on('drain', function() {
- var start = +new Date;
+ var start = Date.now();
require('dirty')(DB_FILE).on('load', function(length) {
- var ms = +new Date - start,
+ var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2),
million = COUNT / 1e6;
diff --git a/benchmark/dirty/set-drain-256-bytes-per-doc.js b/benchmark/dirty/set-drain-256-bytes-per-doc.js
index b77f0ad..74ba236 100644
--- a/benchmark/dirty/set-drain-256-bytes-per-doc.js
+++ b/benchmark/dirty/set-drain-256-bytes-per-doc.js
@@ -1,16 +1,16 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e5,
- dirty = require('dirty')(__dirname+'/../../test/tmp/benchmark-set-drain.dirty'),
+ dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set-drain.dirty'),
util = require('util'),
drained = false;
-var start = +new Date;
+var start = Date.now();
for (var i = 0; i < COUNT; i++) {
dirty.set(i, 'This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string has 256 bytes. This string');
}
dirty.on('drain', function() {
- var ms = +new Date - start,
+ var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2),
million = COUNT / 1e6;
diff --git a/benchmark/dirty/set-drain.js b/benchmark/dirty/set-drain.js
index 35ae88b..c9a4015 100644
--- a/benchmark/dirty/set-drain.js
+++ b/benchmark/dirty/set-drain.js
@@ -1,16 +1,16 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e4,
- dirty = require('dirty')(__dirname+'/../../test/tmp/benchmark-set-drain.dirty'),
+ dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set-drain.dirty'),
util = require('util'),
drained = false;
-var start = +new Date;
+var start = Date.now();
for (var i = 0; i < COUNT; i++) {
dirty.set(i, i);
}
dirty.on('drain', function() {
- var ms = +new Date - start,
+ var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e3).toFixed(2),
million = COUNT / 1e6;
diff --git a/benchmark/dirty/set.js b/benchmark/dirty/set.js
index 8083f45..3c847da 100644
--- a/benchmark/dirty/set.js
+++ b/benchmark/dirty/set.js
@@ -1,18 +1,16 @@
-require('../../test/common');
+var config = require('../../test/config');
var COUNT = 1e6,
- dirty = require('dirty')(__dirname+'/../../test/tmp/benchmark-set.dirty'),
+ dirty = require(config.LIB_DIRTY)(config.TMP_PATH + '/benchmark-set.dirty'),
util = require('util');
-var start = +new Date;
+var start = Date.now();
for (var i = 0; i < COUNT; i++) {
dirty.set(i, i);
}
-var ms = +new Date - start,
+var ms = Date.now() - start,
mhz = ((COUNT / (ms / 1000)) / 1e6).toFixed(2),
million = COUNT / 1e6;
// Can't use console.log() since since I also test this in ancient node versions
util.log(mhz+' Mhz ('+million+' million in '+ms+' ms)');
-process.exit(0);
-
diff --git a/lib/dirty/dirty.js b/lib/dirty/dirty.js
index 41d90ff..80f686f 100644
--- a/lib/dirty/dirty.js
+++ b/lib/dirty/dirty.js
@@ -4,6 +4,10 @@ var fs = require('fs'),
util = require('util'),
EventEmitter = require('events').EventEmitter;
+
+/**
+* Constructor function
+*/
var Dirty = exports.Dirty = function(path) {
if (!(this instanceof Dirty)) return new Dirty(path);
@@ -17,20 +21,29 @@ var Dirty = exports.Dirty = function(path) {
this._queue = [];
this._readStream = null;
this._writeStream = null;
+ this._fdRead = null;
+ this._fdWrite = null;
this._load();
+ return this;
};
util.inherits(Dirty, EventEmitter);
Dirty.Dirty = Dirty;
module.exports = Dirty;
+
+/**
+* set() stores a JSON object in the database at key
+* cb is fired when the data is persisted.
+* In memory, this is immediate- on disk, it will take some time.
+*/
Dirty.prototype.set = function(key, val, cb) {
if (val === undefined) {
- this._keys.splice(this._keys.indexOf(key), 1)
+ this._keys.splice(this._keys.indexOf(key), 1);
delete this._docs[key];
} else {
- if (this._keys.indexOf(key) === -1) {
+ if (this._keys.indexOf(key) === -1) {
this._keys.push(key);
}
this._docs[key] = val;
@@ -45,18 +58,32 @@ Dirty.prototype.set = function(key, val, cb) {
this._maybeFlush();
};
+/**
+* Get the value stored at a key in the database
+* This is synchronous since a cache is maintained in-memory
+*/
Dirty.prototype.get = function(key) {
return this._docs[key];
};
+/**
+* Get total number of stored keys
+*/
Dirty.prototype.size = function() {
return this._keys.length;
};
+/**
+* Remove a key and the value stored there
+*/
Dirty.prototype.rm = function(key, cb) {
this.set(key, undefined, cb);
};
+
+/**
+* Iterate over keys, applying match function
+*/
Dirty.prototype.forEach = function(fn) {
for (var i = 0; i < this._keys.length; i++) {
@@ -68,6 +95,31 @@ Dirty.prototype.forEach = function(fn) {
};
+/**
+ * Close dirty db file stream, release file handle
+ */
+Dirty.prototype.close = function() {
+
+ if (!this.path) {
+ return;
+ }
+
+ this._maybeFlush();
+
+ var self = this;
+ if (this._fdRead) {
+ fs.close(this._fdRead, function() {
+ self.emit('read_close');
+ });
+ }
+ if (this._fdWrite) {
+ fs.close(this._fdWrite, function() {
+ self.emit('write_close');
+ });
+ }
+};
+
+// Called when a dirty connection is instantiated
Dirty.prototype._load = function() {
var self = this, buffer = '', length = 0;
@@ -100,10 +152,12 @@ Dirty.prototype._load = function() {
arr.forEach(function(rowStr) {
if (!rowStr) {
self.emit('error', new Error('Empty lines never appear in a healthy database'));
- return
+ return;
}
+
+ var row;
try {
- var row = JSON.parse(rowStr);
+ row = JSON.parse(rowStr);
if (!('key' in row)) {
throw new Error();
}
@@ -119,7 +173,9 @@ Dirty.prototype._load = function() {
delete self._docs[row.key];
} else {
if (!(row.key in self._docs)) {
- self._keys.push(row.key);
+ if(self._keys.indexOf(row.key) === -1){
+ self._keys.push(row.key);
+ }
length++;
}
self._docs[row.key] = row.val;
@@ -132,6 +188,9 @@ Dirty.prototype._load = function() {
self.emit('error', new Error('Corrupted row at the end of the db: '+buffer));
}
self.emit('load', length);
+ })
+ .on('open', function(fd) {
+ self._fdRead = fd;
});
this._writeStream = fs.createWriteStream(this.path, {
@@ -142,17 +201,21 @@ Dirty.prototype._load = function() {
this._writeStream.on('drain', function() {
self._writeDrain();
});
+
+ this._writeStream.on('open', function(fd) {
+ self._fdWrite = fd;
+ });
};
Dirty.prototype._writeDrain = function() {
this.flushing = false;
-
+
if (!this._queue.length) {
this.emit('drain');
} else {
this._maybeFlush();
}
-}
+};
Dirty.prototype._maybeFlush = function() {
if (this.flushing || !this._queue.length) {
@@ -193,6 +256,8 @@ Dirty.prototype._flush = function() {
}
(function(cbs) {
+ var isDrained;
+
if (!self.path) {
process.nextTick(function() {
callbacks(null, cbs);
@@ -201,7 +266,11 @@ Dirty.prototype._flush = function() {
return;
}
- self._writeStream.write(bundleStr, function(err) {
+ isDrained = self._writeStream.write(bundleStr, function(err) {
+ if (isDrained) {
+ self._writeDrain();
+ }
+
if (!cbs.length && err) {
self.emit('error', err);
return;
@@ -209,6 +278,7 @@ Dirty.prototype._flush = function() {
callbacks(err, cbs);
});
+
})(cbs);
bundleStr = '';
diff --git a/package.json b/package.json
index 78d48de..c317982 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,17 @@
{
"name": "dirty",
"description": "A tiny & fast key value store with append-only disk log. Ideal for apps with < 1 million records.",
- "version": "0.9.6",
+ "version": "1.0.0",
"dependencies": {},
"main": "./lib/dirty",
"devDependencies": {
- "gently": ">=0.8.0"
+ "mocha": "~1.8.2",
+ "rimraf": "~2.1.4"
+ },
+ "scripts": {
+ "test": "./node_modules/mocha/bin/mocha test/test-*.js -R list"
},
"engines": {
"node": "*"
}
-}
\ No newline at end of file
+}
diff --git a/test/common.js b/test/common.js
deleted file mode 100644
index 6c0ad4b..0000000
--- a/test/common.js
+++ /dev/null
@@ -1,17 +0,0 @@
-var path = require('path'), fs = require('fs');
-
-global.ROOT_DIR = path.dirname(__dirname);
-global.TEST_TMP = path.join(__dirname, 'tmp');
-global.ROOT_LIB = path.join(global.ROOT_DIR, 'lib', 'dirty');
-global.assert = require('assert');
-global.Gently = require('gently');
-global.GENTLY = new Gently();
-global.HIJACKED = GENTLY.hijacked;
-
-fs.readdirSync(TEST_TMP).forEach(function(file) {
- if (!file.match(/\.dirty$/)) {
- return;
- }
-
- fs.unlinkSync(TEST_TMP+'/'+file);
-});
diff --git a/test/config.js b/test/config.js
new file mode 100644
index 0000000..fd3976e
--- /dev/null
+++ b/test/config.js
@@ -0,0 +1,14 @@
+var path = require('path'),
+ fs = require('fs'),
+ rimraf = require('rimraf');
+
+var TMP_PATH = path.join(__dirname, 'tmp'),
+ LIB_DIRTY = path.join(__dirname, '../lib/dirty');
+
+rimraf.sync(TMP_PATH);
+fs.mkdirSync(TMP_PATH);
+
+module.exports = {
+ TMP_PATH: TMP_PATH,
+ LIB_DIRTY: LIB_DIRTY
+};
diff --git a/test/nostore/test-load-event.js b/test/nostore/test-load-event.js
deleted file mode 100644
index 807b26a..0000000
--- a/test/nostore/test-load-event.js
+++ /dev/null
@@ -1,13 +0,0 @@
-require('../common');
-var assert = require('assert');
-
-var dirty = require('dirty')('');
-var isLoaded = false;
-
-dirty.on('load', function() {
- isLoaded = true;
-});
-
-setTimeout(function() {
- assert.equal(isLoaded, true);
-}, 500);
\ No newline at end of file
diff --git a/test/nostore/test-set-callback.js b/test/nostore/test-set-callback.js
deleted file mode 100644
index b513dee..0000000
--- a/test/nostore/test-set-callback.js
+++ /dev/null
@@ -1,13 +0,0 @@
-require('../common');
-var assert = require('assert');
-
-var dirty = require('dirty')('');
-var foo = '';
-
-dirty.set('foo', 'bar', function() {
- foo = dirty.get('foo');
-});
-
-setTimeout(function() {
- assert.equal(foo, 'bar');
-}, 500);
\ No newline at end of file
diff --git a/test/simple/test-dirty.js b/test/simple/test-dirty.js
deleted file mode 100644
index 3b60560..0000000
--- a/test/simple/test-dirty.js
+++ /dev/null
@@ -1,330 +0,0 @@
-require('../common');
-var Dirty = require('dirty'),
- EventEmitter = require('events').EventEmitter,
- dirtyLoad = Dirty.prototype._load,
- gently,
- dirty;
-
-(function testConstructor() {
- var gently = new Gently();
-
- (function testBasic() {
- var PATH = '/foo/bar';
- Dirty.prototype._load = gently.expect(function() {
- assert.equal(this.path, PATH);
- });
- var dirty = new Dirty(PATH);
-
- assert.ok(dirty instanceof EventEmitter);
- assert.deepEqual(dirty._docs, {});
- assert.deepEqual(dirty._queue, []);
- assert.strictEqual(dirty.writeBundle, 1000);
- assert.strictEqual(dirty._writeStream, null);
- assert.strictEqual(dirty._readStream, null);
- })();
-
- (function testWithoutNew() {
- Dirty.prototype._load = gently.expect(function() {});
- var dirty = Dirty();
- })();
-
- (function testOldSchoolClassName() {
- assert.strictEqual(Dirty, Dirty.Dirty);
- })();
-
- Dirty.prototype._load = function(){};
- gently.verify();
-})();
-
-function test(fn) {
- gently = new Gently();
- dirty = Dirty();
- fn();
- gently.verify();
-}
-
-test(function _load() {
- (function testNoPath() {
- gently.expect(HIJACKED.fs, 'createWriteStream', 0);
- dirtyLoad.call(dirty);
- })();
-
- (function testWithPath() {
- var PATH = dirty.path = '/dirty.db',
- READ_STREAM = {},
- WRITE_STREAM = {},
- readStreamEmit = {};
-
- gently.expect(HIJACKED.fs, 'createReadStream', function (path, options) {
- assert.equal(path, PATH);
- assert.equal(options.flags, 'r');
- assert.equal(options.encoding, 'utf-8');
-
- return READ_STREAM;
- });
-
- var EVENTS = ['error', 'data', 'end'];
- gently.expect(READ_STREAM, 'on', EVENTS.length, function (event, cb) {
- assert.strictEqual(event, EVENTS.shift());
- readStreamEmit[event] = cb;
- return this;
- });
-
- gently.expect(HIJACKED.fs, 'createWriteStream', function (path, options) {
- assert.equal(path, PATH);
- assert.equal(options.flags, 'a');
- assert.equal(options.encoding, 'utf-8');
-
- return WRITE_STREAM;
- });
-
- gently.expect(WRITE_STREAM, 'on', function (event, cb) {
- assert.strictEqual(event, 'drain');
-
- (function testQueueEmpty() {
- dirty._queue = [];
- dirty.flushing = true;
-
- gently.expect(dirty, 'emit', function (event) {
- assert.strictEqual(event, 'drain');
- });
-
- cb();
- assert.strictEqual(dirty.flushing, false);
- })();
-
- (function testQueueNotEmpty() {
- dirty._queue = [1];
- dirty.flushing = true;
-
- gently.expect(dirty, '_maybeFlush');
-
- cb();
- assert.strictEqual(dirty.flushing, false);
- })();
- });
-
- dirtyLoad.call(dirty);
-
- assert.strictEqual(dirty._writeStream, WRITE_STREAM);
- assert.strictEqual(dirty._readStream, READ_STREAM);
-
- (function testReading() {
- readStreamEmit.data(
- JSON.stringify({key: 1, val: 'A'})+'\n'+
- JSON.stringify({key: 2, val: 'B'})+'\n'
- );
-
- assert.equal(dirty.get(1), 'A');
- assert.equal(dirty.get(2), 'B');
-
- readStreamEmit.data('{"key": 3');
- readStreamEmit.data(', "val": "C"}\n');
- assert.equal(dirty.get(3), 'C');
-
- readStreamEmit.data(
- JSON.stringify({key: 3, val: 'C2'})+'\n'+
- JSON.stringify({key: 4, val: undefined})+'\n'
- );
-
- gently.expect(dirty, 'emit', function (event, err) {
- assert.equal(event, 'error');
- assert.equal(err.message, 'Could not load corrupted row: {broken');
- });
- readStreamEmit.data('{broken\n');
-
- gently.expect(dirty, 'emit', function (event, err) {
- assert.equal(event, 'error');
- assert.equal(err.message, 'Could not load corrupted row: {}');
- });
- readStreamEmit.data('{}\n');
-
- readStreamEmit.data(
- JSON.stringify({key: 1, val: undefined})+'\n'
- );
- assert.ok(!('1' in dirty._docs));
- })();
-
- (function testReadEnd() {
- gently.expect(dirty, 'emit', function (event, length) {
- assert.equal(event, 'load');
- assert.equal(length, 2);
- });
- readStreamEmit.end();
- })();
-
- (function testReadEndWithStuffLeftInBuffer() {
- readStreamEmit.data('foo');
-
- gently.expect(dirty, 'emit', function (event, err) {
- assert.equal(event, 'error');
- assert.equal(err.message, 'Corrupted row at the end of the db: foo');
- });
-
- gently.expect(dirty, 'emit', function (event) {
- assert.equal(event, 'load');
- });
- readStreamEmit.end();
- })();
-
- (function testReadDbError() {
- var ERR = new Error('oh oh');
- gently.expect(dirty, 'emit', function (event, err) {
- assert.equal(event, 'error');
- assert.strictEqual(err, ERR);
- });
- readStreamEmit.error(ERR)
- })();
-
- (function testReadNonexistingDbError() {
- gently.expect(dirty, 'emit', function (event, length) {
- assert.equal(event, 'load');
- assert.equal(length, 0);
- });
- readStreamEmit.error({ code: 'ENOENT' })
- })();
- })();
-});
-
-test(function get() {
- var KEY = 'example', VAL = {};
- dirty._docs[KEY] = VAL;
-
- assert.strictEqual(dirty.get(KEY), VAL);
-});
-
-test(function set() {
- (function testNoCallback() {
- var KEY = 'example', VAL = {};
- gently.expect(dirty, '_maybeFlush');
- dirty.set(KEY, VAL);
- assert.strictEqual(dirty._docs[KEY], VAL);
- assert.strictEqual(dirty._queue[0], KEY);
- })();
-
- (function testCallback() {
- var KEY = 'example', VAL = {}, CB = function() {};
- gently.expect(dirty, '_maybeFlush');
- dirty.set(KEY, VAL, CB);
- assert.strictEqual(dirty._queue[1][0], KEY);
- assert.strictEqual(dirty._queue[1][1], CB);
- })();
-
- (function testUndefinedActsAsRemove() {
- var KEY = 'example', VAL = undefined;
- gently.expect(dirty, '_maybeFlush');
- dirty.set(KEY, VAL);
-
- assert.ok(!(KEY in dirty._docs));
- })();
-});
-
-test(function _maybeFlush() {
- (function testNothingToFlush() {
- gently.expect(dirty, '_flush', 0);
- dirty._maybeFlush();
- })();
-
- (function testFlush() {
- dirty.flushing = false;
- dirty.path = '/foo/bar';
- dirty._queue = [1];
-
- gently.expect(dirty, '_flush');
- dirty._maybeFlush();
- })();
-
- (function testOneFlushAtATime() {
- dirty.flushing = true;
-
- gently.expect(dirty, '_flush', 0);
- dirty._maybeFlush();
- })();
-
- (function testNoFlushingWithoutPath() {
- dirty.flushing = false;
- dirty.path = null;
-
- gently.expect(dirty, '_flush', 0);
- dirty._maybeFlush();
- })();
-
- (function testNoFlushingWithoutQueue() {
- dirty.flushing = false;
- dirty.path = '/foo/bar';
- dirty._queue = [];
-
- gently.expect(dirty, '_flush', 0);
- dirty._maybeFlush();
- })();
-});
-
-test(function _flush() {
- var WRITE_STREAM = dirty._writeStream = {}, CB;
- var ERR = new Error('oh oh');
-
- gently.expect(WRITE_STREAM, 'write', function (str, cb) {
- assert.strictEqual(dirty.flushing, true);
- assert.equal(
- str,
- JSON.stringify({key: 'foo', val: 1})+'\n'+
- JSON.stringify({key: 'bar', val: 2})+'\n'
- );
-
- cb(ERR);
- });
-
- var BAR_CB = gently.expect(function writeCb(err) {
- assert.strictEqual(err, ERR);
- });
-
- var ERR2 = new Error('oh oh');
-
- gently.expect(WRITE_STREAM, 'write', function (str, cb) {
- assert.equal(str, JSON.stringify({key: 'test', val: 3})+'\n');
-
- cb(ERR2);
- });
-
- gently.expect(dirty, 'emit', function (event, err) {
- assert.strictEqual(event, 'error');
- assert.strictEqual(err, ERR2);
- });
-
- dirty.writeBundle = 2;
- dirty._docs = {foo: 1, bar: 2, test: 3};
- dirty._queue = ['foo', ['bar', BAR_CB], 'test'];
-
- dirty._flush();
-
- assert.deepEqual(dirty._queue, []);
-});
-
-test(function rm() {
- var KEY = 'foo', CB = function() {};
- gently.expect(dirty, 'set', function (key, val, cb) {
- assert.strictEqual(key, KEY);
- assert.strictEqual(val, undefined);
- assert.strictEqual(cb, CB);
- });
- dirty.rm(KEY, CB);
-});
-
-test(function forEach() {
- for (var i = 1; i <= 4; i++) {
- dirty.set(i, {});
- };
-
- var i = 0;
- dirty.forEach(function(key, doc) {
- i++;
- assert.equal(key, i);
- assert.strictEqual(doc, dirty._docs[i]);
-
- if (i == 3) {
- return false;
- }
- });
-
- assert.equal(i, 3);
-});
diff --git a/test/system/test-flush.js b/test/system/test-flush.js
deleted file mode 100644
index b18b6f7..0000000
--- a/test/system/test-flush.js
+++ /dev/null
@@ -1,12 +0,0 @@
-require('../common');
-var DB_FILE = TEST_TMP+'/flush.dirty';
- db = require('dirty')(DB_FILE),
- fs = require('fs');
-
-db.set('foo', 'bar');
-db.on('drain', function() {
- assert.strictEqual(
- fs.readFileSync(DB_FILE, 'utf-8'),
- JSON.stringify({key: 'foo', 'val': 'bar'})+'\n'
- );
-});
diff --git a/test/system/test-for-each.js b/test/system/test-for-each.js
deleted file mode 100644
index 7212e31..0000000
--- a/test/system/test-for-each.js
+++ /dev/null
@@ -1,15 +0,0 @@
-require('../common');
-var db = require('dirty')();
-
-db.set(1, {test: 'foo'});
-db.set(2, {test: 'bar'});
-db.set(3, {test: 'foobar'});
-
-var i = 0;
-db.forEach(function(key, doc) {
- i++;
- assert.equal(key, i);
- assert.strictEqual(doc, db.get(key));
-});
-
-assert.equal(i, 3);
diff --git a/test/system/test-load.js b/test/system/test-load.js
deleted file mode 100644
index 21dd88f..0000000
--- a/test/system/test-load.js
+++ /dev/null
@@ -1,29 +0,0 @@
-require('../common');
-var DB_FILE = TEST_TMP+'/load.dirty';
- db = require('dirty')(DB_FILE),
- fs = require('fs'),
- loaded = false;
-
-db.set(1, 'A');
-db.set(2, 'B');
-db.set(3, 'C');
-db.rm(3);
-
-db.on('drain', function() {
- var db2 = require('dirty')(DB_FILE);
- db2.on('load', function(length) {
- loaded = true;
-
- assert.equal(length, 2);
-
- assert.strictEqual(db2.get(1), 'A');
- assert.strictEqual(db2.get(2), 'B');
- assert.strictEqual(db2.get(3), undefined);
- assert.strictEqual(db2._keys.length, 2);
- assert.ok(!('3' in db2._docs));
- });
-});
-
-process.on('exit', function() {
- assert.ok(loaded);
-});
diff --git a/test/system/test-size.js b/test/system/test-size.js
deleted file mode 100644
index ae087e3..0000000
--- a/test/system/test-size.js
+++ /dev/null
@@ -1,8 +0,0 @@
-require('../common');
-var db = require(global.ROOT_LIB)();
-
-db.set(1, {test: 'foo'});
-db.set(2, {test: 'bar'});
-db.set(3, {test: 'foobar'});
-
-assert.equal(db.size(), 3);
diff --git a/test/test-api.js b/test/test-api.js
new file mode 100644
index 0000000..6668df8
--- /dev/null
+++ b/test/test-api.js
@@ -0,0 +1,158 @@
+var config = require('./config');
+ path = require('path'),
+ fs = require('fs'),
+ dirty = require(config.LIB_DIRTY),
+ events = require('events'),
+ assert = require('assert');
+
+// exists moved from path to fs in node v0.7.1
+// https://raw.github.com/joyent/node/v0.7.1/ChangeLog
+var exists = (fs.exists) ? fs.exists : path.exists;
+
+function dirtyAPITests(file) {
+ var mode = (file) ? 'persistent' : 'transient';
+
+ describe('dirty api (' + mode + ' mode)', function() {
+ function cleanup(done) {
+ exists(file, function(doesExist) {
+ if (doesExist) {
+ fs.unlinkSync(file);
+ }
+
+ done();
+ });
+ }
+
+ before(cleanup);
+
+ describe('dirty constructor', function() {
+ var db = dirty(file);
+
+ after(cleanup);
+
+ it('is an event emitter', function() {
+ assert.ok(db instanceof events.EventEmitter);
+ });
+
+ it('is a dirty', function() {
+ assert.ok(db instanceof dirty);
+ });
+
+ });
+
+ describe('events', function() {
+
+ afterEach(cleanup);
+
+ it('should fire load', function(done) {
+ var db = dirty(file);
+ db.on('load', function(length) {
+ assert.strictEqual(length, 0);
+ done();
+ });
+ });
+
+ it('should fire drain after write', function(done) {
+ var db = dirty(file);
+ db.on('load', function(length) {
+ assert.strictEqual(length, 0);
+
+ db.set('key', 'value');
+ db.on('drain', function() {
+ done();
+ });
+
+ });
+ });
+ });
+
+ describe('accessors', function(done) {
+ after(cleanup);
+ var db;
+
+ it('.set should trigger callback', function(done) {
+ db = dirty(file);
+ db.set('key', 'value', function(err) {
+ assert.ok(!err);
+ done();
+ });
+ });
+
+ it('.get should return value', function() {
+ assert.strictEqual(db.get('key'), 'value');
+ });
+
+ it('.path is valid', function() {
+ assert.strictEqual(db.path, file);
+ });
+
+ it('.forEach runs for all', function() {
+ var total = 2, count = 0;
+ db.set('key1', 'value1');
+ db.set('delete', 'me');
+
+ db.rm('delete');
+
+ var keys = ['key', 'key1'];
+ var vals = ['value', 'value1'];
+
+ db.forEach(function(key, val) {
+ assert.strictEqual(key, keys[count]);
+ assert.strictEqual(val, vals[count]);
+
+ count ++;
+ });
+
+ assert.strictEqual(count, total);
+ });
+
+ it('.rm removes key/value pair', function() {
+ db.set('test', 'test');
+ assert.strictEqual(db.get('test'), 'test');
+ db.rm('test');
+ assert.strictEqual(db.get('test'), undefined);
+ });
+
+ it('will reload file from disk', function(done) {
+ if (!file) {
+ console.log('N/A in transient mode');
+ return done();
+ }
+
+ db = dirty(file);
+ db.on('load', function(length) {
+ assert.strictEqual(length, 2);
+ assert.strictEqual(db.get('key'), 'value');
+ assert.strictEqual(db.get('key1'), 'value1');
+ done();
+ });
+ });
+ });
+
+ describe('db file close', function(done) {
+ after(cleanup);
+
+ it('close', function(done) {
+ if (!file) {
+ console.log('N/A in transient mode');
+ return done();
+ }
+ var db = dirty(file);
+ db.on('load', function(length) {
+ db.set('close', 'close');
+ db.on('drain', function() {
+ db.close();
+ });
+ });
+
+ db.on('write_close',function() {
+ done();
+ });
+ });
+ });
+
+ });
+}
+
+dirtyAPITests('');
+dirtyAPITests(config.TMP_PATH + '/apitest.dirty');
diff --git a/test/test-nostore.js b/test/test-nostore.js
new file mode 100644
index 0000000..23474ad
--- /dev/null
+++ b/test/test-nostore.js
@@ -0,0 +1,31 @@
+var config = require('./config'),
+ dirty = require(config.LIB_DIRTY),
+ assert = require('assert'),
+ fs = require('fs');
+
+describe('test-load-event', function() {
+ it('should fire load event', function(done) {
+ var db = dirty();
+
+ db.on('load', function() {
+ done();
+ });
+ });
+
+});
+
+describe('test-set-callback', function() {
+
+ it ('should trigger callback on set', function(done) {
+ var db = dirty();
+ var foo = '';
+
+ db.set('foo', 'bar', function() {
+ foo = db.get('foo');
+ assert.equal(foo, 'bar');
+ done();
+ });
+
+ });
+
+});
diff --git a/test/test-system.js b/test/test-system.js
new file mode 100644
index 0000000..791b6e2
--- /dev/null
+++ b/test/test-system.js
@@ -0,0 +1,118 @@
+var config = require('./config'),
+ fs = require('fs'),
+ assert = require('assert'),
+ dirty = require(config.LIB_DIRTY);
+
+describe('test-flush', function() {
+ var file = config.TMP_PATH + '/flush.dirty';
+
+ afterEach(function() {
+ fs.unlinkSync(file);
+ });
+
+ it ('should fire drain event on write', function(done) {
+ var db = dirty(file);
+ db.set('foo', 'bar');
+ db.on('drain', function() {
+ done();
+ });
+ });
+
+ it ('should write to disk appropriately', function(done) {
+ var db = dirty(file);
+ db.set('foo1', 'bar1');
+ db.on('drain', function() {
+ var contents = fs.readFileSync(file, 'utf-8');
+
+ assert.strictEqual(
+ contents,
+ JSON.stringify({key: 'foo1', val: 'bar1'})+'\n'
+ );
+
+ done();
+ });
+ });
+
+});
+
+describe('test-for-each', function() {
+ var db = dirty();
+
+ db.set(1, {test: 'foo'});
+ db.set(2, {test: 'bar'});
+ db.set(3, {test: 'foobar'});
+
+ it('should return each doc key and contents', function() {
+ var i = 0;
+ db.forEach(function(key, doc) {
+ i++;
+ assert.equal(key, i);
+ assert.strictEqual(doc, db.get(key));
+ });
+ assert.equal(i, 3);
+ });
+});
+
+describe('test-load', function() {
+ var file = config.TMP_PATH +'/load.dirty',
+ db = dirty(file);
+
+ afterEach(function() {
+ fs.unlinkSync(file);
+ });
+
+ it('should load after write to disk', function(done) {
+ db.set(1, 'A');
+ db.set(2, 'B');
+ db.set(3, 'C');
+ db.rm(3);
+
+ db.on('drain', function() {
+ var db2 = dirty(file);
+
+ db2.on('load', function(length) {
+ assert.equal(length, 2);
+
+ assert.strictEqual(db2.get(1), 'A');
+ assert.strictEqual(db2.get(2), 'B');
+ assert.strictEqual(db2.get(3), undefined);
+ assert.strictEqual(db2._keys.length, 2);
+ assert.ok(!('3' in db2._docs));
+ done();
+ });
+ });
+
+ });
+});
+
+
+describe('test-size', function() {
+ var db = dirty();
+
+ db.set(1, {test: 'foo'});
+ db.set(2, {test: 'bar'});
+ db.set(3, {test: 'foobar'});
+
+ it('should be equal to number of keys set', function() {
+ assert.equal(db.size(), 3);
+ });
+});
+
+describe('test-chaining-of-constructor', function() {
+ var file = config.TMP_PATH + '/chain.dirty';
+ fs.existsSync(file) && fs.unlinkSync(file);
+
+ it('should allow .on load to chain to constructor', function() {
+ var db = dirty(file);
+ db.on('load', function() {
+ db.set("x", "y");
+ db.set("p", "q");
+ db.close();
+
+ db = dirty(file).on('load', function(size) {
+ assert.strictEqual(db.size(), 2);
+ assert.strictEqual(size, 2);
+ });
+ });
+ });
+});
diff --git a/test/test-types.js b/test/test-types.js
new file mode 100644
index 0000000..3fef069
--- /dev/null
+++ b/test/test-types.js
@@ -0,0 +1,19 @@
+var config = require('./config'),
+ fs = require('fs'),
+ dirty = require(config.LIB_DIRTY),
+ assert = require('assert');
+
+describe.skip('test-types', function() {
+ var db = dirty(config.TMP_PATH + '/test-types.dirty');
+
+ describe('keys', function() {
+ it('should prevent storage of an undefined key', function() {
+ db.set(undefined, 'value');
+ });
+
+ it('should not return an undefined key', function() {
+ assert(!db.get(undefined));
+ });
+ });
+
+});
diff --git a/test/tmp/.empty b/test/tmp/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/test/undefined-key.js b/test/undefined-key.js
new file mode 100644
index 0000000..607238a
--- /dev/null
+++ b/test/undefined-key.js
@@ -0,0 +1,19 @@
+require('../common');
+
+var db = require('Dirty')('undef-key.dirty');
+
+db.set('now', Date.now());
+
+db.set('gobble', 'adfasdf');
+
+db.set('now', undefined, function() {
+ // callback?
+ // impossible yes?!
+ console.log('blamo!')
+});
+
+db.set(undefined);
+
+console.log(db.get('now'));
+
+// db = require('Dirty')('undef-key.dirty');
\ No newline at end of file
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/dirty.js.git
More information about the Pkg-javascript-commits
mailing list