diff --git a/api/database.js b/api/database.js index c15e69815..199f37c84 100644 --- a/api/database.js +++ b/api/database.js @@ -35,6 +35,7 @@ DatabaseError.SERVER_ERROR = 1; DatabaseError.INTERNAL_ERROR = 2; DatabaseError.ALREADY_EXISTS = 3; DatabaseError.NOT_FOUND = 4; +DatabaseError.RECORD_SCHEMA = 5; function Table(dbFile, schema) { this.dbFile = dbFile; @@ -57,6 +58,7 @@ function Table(dbFile, schema) { Table.prototype.put = function (user, callback) { var key = user[this.hashKey]; + if (!key) return callback(new DatabaseError('no hash key found', DatabaseError.RECORD_SCHEMA)); if (key in this.cache) return callback(new DatabaseError(null, DatabaseError.ALREADY_EXISTS)); this.cache[key] = user; @@ -64,12 +66,22 @@ Table.prototype.put = function (user, callback) { callback(); }; +Table.prototype.update = function (user, callback) { + var key = user[this.hashKey]; + if (!key) return callback(new DatabaseError('no hash key found', DatabaseError.RECORD_SCHEMA)); + if (!(key in this.cache)) return callback(new DatabaseError(null, DatabaseError.NOT_FOUND)); + + this.cache[key] = user; + fs.writeFileSync(this.dbFile, JSON.stringify(this.cache)); + callback(); +}; + Table.prototype.get = function (key, callback) { if (key in this.cache) return callback(null, this.cache[key]); return callback(new DatabaseError(null, DatabaseError.NOT_FOUND)); }; -Table.prototype.count = function (callback) { +Table.prototype.count = function () { var i = 0; for (var e in this.cache) { @@ -78,10 +90,6 @@ Table.prototype.count = function (callback) { } } - if (typeof callback === 'function') { - callback(i); - } - return i; }; diff --git a/api/test/database-test.js b/api/test/database-test.js new file mode 100644 index 000000000..5a16f70ed --- /dev/null +++ b/api/test/database-test.js @@ -0,0 +1,288 @@ +'use strict'; + +/* global it:false */ +/* global describe:false */ +/* global before:false */ +/* global after:false */ + +var db = require('../database.js'), + DatabaseError = db.DatabaseError, + os = require('os'), + path = require('path'), + mkdirp = require('mkdirp'), + rimraf = require('rimraf'), + assert = require('assert'), + crypto = require('crypto'), + expect = require('expect.js'); + +var USER_0 = { + username: 'girish', + email: 'mail@g.irish', + password: 'hsirig' +}; + +var USER_1 = { + username: 'johannes', + email: 'mail@j.ohannes', + password: 'sennahoj' +}; + +var tmpdirname = 'database-test-' + crypto.randomBytes(4).readUInt32LE(0); +var config = { + port: 3000, + dataRoot: path.resolve(os.tmpdir(), tmpdirname + '/data'), + configRoot: path.resolve(os.tmpdir(), tmpdirname + '/config'), + mountRoot: path.resolve(os.tmpdir(), tmpdirname + '/mount') +}; + +// ensure data/config/mount paths +function setup(done) { + mkdirp.sync(config.dataRoot); + mkdirp.sync(config.configRoot); + mkdirp.sync(config.mountRoot); + + done(); +} + +// remove all temporary folders +function cleanup(done) { + rimraf(config.dataRoot, function (error) { + rimraf(config.configRoot, function (error) { + rimraf(config.mountRoot, function (error) { + done(); + }); + }); + }); +} + +describe('Database', function () { + before(setup); + after(cleanup); + + describe('initialize', function() { + it('succeeds', function (done) { + db.initialize(config); + + done(); + }); + + it('creates table exports', function (done) { + expect(db.USERS_TABLE).to.be.an(db.Table); + expect(db.TOKENS_TABLE).to.be.an(db.Table); + + done(); + }); + + it('firstTime', function (done) { + expect(db.firstTime()).to.be.ok(); + done(); + }); + }); + + describe('CRUD on USERS_TABLE', function () { + describe('put', function () { + it('succeeds', function (done) { + db.USERS_TABLE.put(USER_0, function (error) { + expect(error).to.not.be.ok(); + done(); + }); + }); + + it('fails of duplicate', function (done) { + db.USERS_TABLE.put(USER_0, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.ALREADY_EXISTS); + done(); + }); + }); + + it('fails of wrong record structure', function (done) { + db.USERS_TABLE.put({}, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.RECORD_SCHEMA); + done(); + }); + }); + }); + + describe('get', function () { + it('succeeds', function (done) { + db.USERS_TABLE.get(USER_0.username, function (error, result) { + expect(error).to.not.be.ok(); + expect(result).to.be.ok(); + expect(result).to.equal(USER_0); + done(); + }); + }); + + it('fails because of no such key', function (done) { + db.USERS_TABLE.get('randomkey', function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + + it('fails because of null key', function (done) { + db.USERS_TABLE.get(null, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + + it('fails because of undefined key', function (done) { + db.USERS_TABLE.get(undefined, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + }); + + describe('update', function () { + it('succeeds', function (done) { + var tmp = USER_0; + tmp.email = 'something@el.se'; + + db.USERS_TABLE.update(tmp, function (error) { + expect(error).to.not.be.ok(); + + db.USERS_TABLE.get(tmp.username, function (error, result) { + expect(error).to.not.be.ok(); + expect(result).to.be.ok(); + expect(result).to.equal(tmp); + done(); + }); + }); + }); + + it('fails of no such key', function (done) { + db.USERS_TABLE.update(USER_1, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + + it('fails of wrong record schema', function (done) { + db.USERS_TABLE.update({}, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.RECORD_SCHEMA); + done(); + }); + }); + + it('fails because of wrong arguments', function (done) { + expect(function () { + db.USERS_TABLE.update(null, function () {}); + }).to.throwException(); + expect(function () { + db.USERS_TABLE.update(undefined, function () {}); + }).to.throwException(); + done(); + }); + }); + + describe('remove', function () { + it('succeeds', function (done) { + db.USERS_TABLE.remove(USER_0.username, function (error) { + expect(error).to.not.be.ok(); + + db.USERS_TABLE.get(USER_0.username, function (error, result) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + expect(result).to.not.be.ok(); + done(); + }); + }); + }); + + it('fails of no such key', function (done) { + db.USERS_TABLE.remove(USER_1, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + + it('fails because of null key', function (done) { + db.USERS_TABLE.remove(null, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + + it('fails because of undefined key', function (done) { + db.USERS_TABLE.remove(undefined, function (error) { + expect(error).to.be.ok(); + expect(error.reason).to.equal(DatabaseError.NOT_FOUND); + done(); + }); + }); + }); + + }); + + describe('count', function () { + it('increment', function (done) { + expect(db.USERS_TABLE.count()).to.equal(0); + + db.USERS_TABLE.put(USER_0, function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(1); + + db.USERS_TABLE.put(USER_1, function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(2); + done(); + }); + }); + }); + + it('decrement', function (done) { + expect(db.USERS_TABLE.count()).to.equal(2); + + db.USERS_TABLE.remove(USER_0.username, function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(1); + + db.USERS_TABLE.remove(USER_1.username, function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(0); + done(); + }); + }); + }); + }); + + describe('removeAll', function () { + it('succeeds', function (done) { + db.USERS_TABLE.put(USER_0, function (error) { + expect(error).to.not.be.ok(); + + db.USERS_TABLE.put(USER_1, function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(2); + + db.USERS_TABLE.removeAll(function (error) { + expect(error).to.not.be.ok(); + expect(db.USERS_TABLE.count()).to.equal(0); + done(); + }); + }); + }); + }); + }); + + describe('remove privates', function () { + it('succeeds', function (done) { + var tmp = db.USERS_TABLE.removePrivates(USER_0); + expect(tmp.password).to.not.be.ok(); + expect(tmp.username).to.be.ok(); + expect(tmp.username).to.equal(USER_0.username); + done(); + }); + }); +});