455 lines
14 KiB
JavaScript
455 lines
14 KiB
JavaScript
var fb = require('../lib');
|
|
var fs = require('fs');
|
|
var os = require('os');
|
|
|
|
var assert = require('assert');
|
|
var Path = require('path');
|
|
var now = new Date();
|
|
|
|
var config = {
|
|
|
|
// Problem with privileges in OSX
|
|
// database: Path.join(os.tmpdir(), 'test-' + new Date().getTime() + '.fdb'),
|
|
|
|
database: Path.join(process.cwd(), 'test-' + new Date().getTime() + '.fdb'),
|
|
host: '127.0.0.1', // default
|
|
port: 3050, // default
|
|
user: 'SYSDBA', // default
|
|
password: 'masterkey', // default
|
|
role: null, // default
|
|
pageSize: 4096, // default when creating database
|
|
timeout: 3000 // default query timeout
|
|
}
|
|
|
|
Array.prototype.async = function(cb) {
|
|
|
|
var self = this;
|
|
var item = self.shift();
|
|
|
|
if (item === undefined) {
|
|
if (cb)
|
|
cb();
|
|
return;
|
|
}
|
|
|
|
item(function() {
|
|
setImmediate(function() {
|
|
self.async(cb);
|
|
});
|
|
});
|
|
};
|
|
|
|
fb.attachOrCreate(config, function (err, db) {
|
|
|
|
if (err)
|
|
throw err.message;
|
|
|
|
database = db;
|
|
|
|
var task = [];
|
|
|
|
task.push(test_create);
|
|
task.push(test_reconnect);
|
|
task.push(test_insert);
|
|
task.push(test_select_insert); // for inserted rows
|
|
task.push(test_update);
|
|
task.push(test_select_update); // for updated rows
|
|
task.push(test_transaction);
|
|
|
|
task.push(function(next) {
|
|
db.detach(next);
|
|
});
|
|
|
|
task.push(test_pooling);
|
|
task.async();
|
|
});
|
|
|
|
function test_create(next) {
|
|
|
|
var name = 'TEST ---> test_create';
|
|
console.time(name);
|
|
|
|
// Create table
|
|
database.query('CREATE TABLE test (ID INT, NAME VARCHAR(50), FILE BLOB, CREATED TIMESTAMP)', function(err) {
|
|
assert.ok(!err, name + ': create table ' + err);
|
|
|
|
// Check if table exists
|
|
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
|
assert.ok(!err, name + ': check existing of table ' + err);
|
|
|
|
assert.ok(r[0].count === 0, name + ': check rows in new table');
|
|
console.timeEnd(name);
|
|
|
|
// Next test
|
|
next();
|
|
});
|
|
});
|
|
}
|
|
|
|
function test_reconnect(next) {
|
|
|
|
var name = 'TEST ---> test_reconnect';
|
|
console.time(name);
|
|
database.connection._socket.end();
|
|
database.on('reconnect', function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
}
|
|
|
|
function test_insert(next) {
|
|
|
|
var name = 'TEST ---> test_insert';
|
|
var query = [];
|
|
|
|
console.time(name);
|
|
|
|
// Insert record with blob (STREAM)
|
|
query.push(function(next) {
|
|
database.query('INSERT INTO test (ID, NAME, FILE, CREATED) VALUES(?, ?, ?, ?) RETURNING ID', [1, 'Firebird 1', fs.createReadStream('image.png'), '14.12.2014 12:12:12'], function(err, r) {
|
|
assert.ok(!err, name + ': insert blob (stream) ' + err);
|
|
assert.ok(r['id'] === 1, name + ': blob (stream) returning value');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Insert record with blob (BUFFER)
|
|
query.push(function(next) {
|
|
database.query('INSERT INTO test (ID, NAME, FILE, CREATED) VALUES(?, ?, ?, ?) RETURNING ID', [2, 'Firebird 2', fs.readFileSync('image.png'), '14.12.2014T12:12:12'], function(err, r) {
|
|
assert.ok(!err, name + ': insert blob (buffer) ' + err);
|
|
assert.ok(r['id'] === 2, name + ': blob (buffer) returning value');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Insert record without blob
|
|
query.push(function(next) {
|
|
database.query('INSERT INTO test (ID, NAME, CREATED) VALUES(?, ?, ?) RETURNING ID', [3, 'Firebird 3', now], function(err, r) {
|
|
assert.ok(!err, name + ': insert without blob (buffer) (1) ' + err);
|
|
assert.ok(r['id'] === 3, name + ': without blob (buffer) returning value');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Insert record without blob (without returning value)
|
|
query.push(function(next) {
|
|
database.query('INSERT INTO test (ID, NAME, CREATED) VALUES(?, ?, ?)', [4, 'Firebird 4', '2014-12-12 13:59'], function(err, r) {
|
|
assert.ok(!err, name + ': insert without blob (buffer) (2) ' + err);
|
|
assert.ok(err === undefined, name + ': insert without blob + without returning value');
|
|
next();
|
|
});
|
|
});
|
|
|
|
query.async(function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
|
|
}
|
|
|
|
function test_update(next) {
|
|
|
|
var name = 'TEST ---> test_update';
|
|
console.time(name);
|
|
|
|
var query = [];
|
|
|
|
// Insert record with blob (STREAM)
|
|
query.push(function(next) {
|
|
database.query('UPDATE test SET NAME=?, FILE=? WHERE Id=1', ['Firebird 1 (UPD)', fs.createReadStream('image.png')], function(err, r) {
|
|
assert.ok(!err, name + ': update blob (stream) ' + err);
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Insert record with blob (BUFFER)
|
|
query.push(function(next) {
|
|
database.query('UPDATE test SET NAME=?, FILE=? WHERE Id=2', ['Firebird 2 (UPD)', fs.readFileSync('image.png')], function(err, r) {
|
|
assert.ok(!err, name + ': update blob (buffer) ' + err);
|
|
next();
|
|
});
|
|
});
|
|
|
|
query.async(function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
|
|
}
|
|
|
|
function test_select_insert(next) {
|
|
|
|
var name = 'TEST ---> test_select_insert';
|
|
console.time(name);
|
|
|
|
var query = [];
|
|
|
|
// Classic select
|
|
query.push(function(next) {
|
|
database.query('SELECT * FROM test', function(err, r) {
|
|
|
|
var row = r[0];
|
|
var row2 = r[2];
|
|
var row4 = r[3];
|
|
|
|
assert.ok(!err, name + ': problem (1) ' + err);
|
|
assert.ok(row !== undefined, name + ': problem (2)');
|
|
assert.ok(row.id === 1 && row.name === 'Firebird 1', name + ': problem with deserializer');
|
|
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
|
assert.ok(row.created.getMonth() === 11 && row.created.getDate() === 14 && row.created.getFullYear() === 2014 && row.created.getHours() === 12 && row.created.getMinutes() === 12, name + ': date problem (1)');
|
|
assert.ok(row2.created.getTime() === now.getTime(), name + ': date problem (2)');
|
|
assert.ok(row4.created.getMonth() === 11 && row4.created.getDate() === 12 && row4.created.getFullYear() === 2014 && row4.created.getHours() === 13 && row4.created.getMinutes() === 59, name + ': date problem (3)');
|
|
|
|
row.file(function(err, name, e) {
|
|
|
|
assert.ok(!err, name + ': reading blob ' + err);
|
|
|
|
var count = 0;
|
|
|
|
e.on('data', function(buffer) {
|
|
count += buffer.length;
|
|
});
|
|
|
|
e.on('end', function() {
|
|
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
|
next();
|
|
});
|
|
});
|
|
|
|
});
|
|
});
|
|
|
|
// Scalar testing
|
|
query.push(function(next) {
|
|
database.query('SELECT CAST(123 as NUMERIC(10,2)) As a, MAX(2) AS b, COUNT(*) AS c FROM RDB$DATABASE', function(err, results) {
|
|
var row = results[0];
|
|
assert.ok(row.a === 123, name + ': cast problem');
|
|
assert.ok(row.b === 2, name + ': max problem');
|
|
assert.ok(row.c !== 0, name + ': count problem');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Select to array
|
|
query.push(function(next) {
|
|
// Deserialize to array
|
|
database.execute('SELECT COUNT(*), SUM(Id) FROM test', function(err, r) {
|
|
assert.ok(r[0][0] === 4 && r[0][1] === 10, name + ': array deserializer problem');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Sequentially select (object)
|
|
query.push(function(next) {
|
|
var counter = 0;
|
|
database.sequentially('SELECT Id FROM test', function(row, index) {
|
|
counter += row.id;
|
|
}, function() {
|
|
assert.ok(counter === 10, name + ': sequentially (object)');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Sequentially select (array)
|
|
query.push(function(next) {
|
|
var counter = 0;
|
|
database.sequentially('SELECT Id FROM test', function(row, index) {
|
|
counter += row[0];
|
|
}, function() {
|
|
assert.ok(counter === 10, name + ': sequentially (array)');
|
|
next();
|
|
}, true);
|
|
});
|
|
|
|
query.async(function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
}
|
|
|
|
function test_select_update(next) {
|
|
|
|
var name = 'TEST ---> test_select_update';
|
|
console.time(name);
|
|
|
|
var query = [];
|
|
|
|
// Classic select 1
|
|
query.push(function(next) {
|
|
database.query('SELECT * FROM test WHERE Id=1', function(err, r) {
|
|
|
|
var row = r[0];
|
|
|
|
assert.ok(!err, name + ': problem (1) ' + err);
|
|
assert.ok(row !== undefined, name + ': problem (2)');
|
|
assert.ok(row.id === 1 && row.name === 'Firebird 1 (UPD)', name + ': problem with deserializer');
|
|
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
|
|
|
row.file(function(err, name, e) {
|
|
|
|
assert.ok(!err, name + ': reading blob');
|
|
|
|
var count = 0;
|
|
|
|
e.on('data', function(buffer) {
|
|
count += buffer.length;
|
|
});
|
|
|
|
e.on('end', function() {
|
|
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
// Classic select 2
|
|
query.push(function(next) {
|
|
database.query('SELECT * FROM test WHERE Id=2', function(err, r) {
|
|
|
|
var row = r[0];
|
|
|
|
assert.ok(!err, name + ': problem (1) ' + err);
|
|
assert.ok(row !== undefined, name + ': problem (2)');
|
|
assert.ok(row.id === 2 && row.name === 'Firebird 2 (UPD)', name + ': problem with deserializer');
|
|
assert.ok(typeof(row.file) === 'function', name + ': blob');
|
|
|
|
row.file(function(err, name, e) {
|
|
|
|
assert.ok(!err, name + ': reading blob');
|
|
|
|
var count = 0;
|
|
|
|
e.on('data', function(buffer) {
|
|
count += buffer.length;
|
|
});
|
|
|
|
e.on('end', function() {
|
|
assert.ok(count === 5472, name + ': problem with retrieving blob data');
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
query.async(function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
}
|
|
|
|
function test_transaction(next) {
|
|
|
|
var name = 'TEST ---> test_transaction';
|
|
console.time(name);
|
|
|
|
var query = [];
|
|
|
|
// Invalid transaction
|
|
query.push(function(next) {
|
|
database.transaction(function(err, transaction) {
|
|
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [5, 'Transaction 1'], function(err) {
|
|
assert.ok(!err, name + ': problem (1) ' + err);
|
|
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [6, 'Transaction 2'], function(err) {
|
|
assert.ok(!err, name + ': problem (2)');
|
|
transaction.query('INSERT INTO testa (ID, NAME) VALUES(?, ?)', [7, 'Transaction 3'], function(err) {
|
|
assert.ok(err, name + ': problem (3)');
|
|
transaction.rollback(function(err) {
|
|
assert.ok(!err, name + ': rollback problem');
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
// Select to array
|
|
query.push(function(next) {
|
|
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
|
assert.ok(r[0].count === 4, name + ': transaction does not work (rollback)');
|
|
next();
|
|
});
|
|
});
|
|
|
|
// Valid transaction
|
|
query.push(function(next) {
|
|
database.transaction(function(err, transaction) {
|
|
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [5, 'Transaction 1'], function(err) {
|
|
assert.ok(!err, name + ': problem (4) ' + err);
|
|
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [6, 'Transaction 2'], function(err) {
|
|
assert.ok(!err, name + ': problem (5)');
|
|
transaction.query('INSERT INTO test (ID, NAME) VALUES(?, ?)', [7, 'Transaction 3'], function(err) {
|
|
assert.ok(!err, name + ': problem (6) ' + err);
|
|
transaction.commit(function(err) {
|
|
assert.ok(!err, name + ': commit problem ' + err);
|
|
next();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
// Select to array
|
|
query.push(function(next) {
|
|
database.query('SELECT COUNT(*) FROM test', function(err, r) {
|
|
assert.ok(r[0].count === 7, name + ': transaction does not work (commit)');
|
|
next();
|
|
});
|
|
});
|
|
|
|
query.async(function() {
|
|
console.timeEnd(name);
|
|
next();
|
|
});
|
|
}
|
|
|
|
function test_pooling(next) {
|
|
|
|
var name = 'TEST ---> test_pooling';
|
|
console.time(name);
|
|
|
|
var query = [];
|
|
var pool = fb.pool(2, config);
|
|
|
|
query.push(function(next) {
|
|
pool.get(function(err, db) {
|
|
setTimeout(function() {
|
|
// detach a current connection (socket is opened)
|
|
db.detach();
|
|
}, 1000);
|
|
next();
|
|
});
|
|
});
|
|
|
|
query.push(function(next) {
|
|
pool.get(function(err, db) {
|
|
setTimeout(function() {
|
|
// detach a current connection (socket is still opened)
|
|
db.detach();
|
|
}, 1500);
|
|
next();
|
|
});
|
|
});
|
|
|
|
query.push(function(next) {
|
|
pool.get(function(err, db) {
|
|
next();
|
|
});
|
|
assert.ok(pool.pending.length > 0, name + ': pool pending');
|
|
});
|
|
|
|
query.push(function(next) {
|
|
setTimeout(function() {
|
|
pool.destroy();
|
|
console.timeEnd(name);
|
|
}, 500);
|
|
next();
|
|
});
|
|
|
|
setTimeout(function() {
|
|
query.async(next);
|
|
}, 1000);
|
|
}
|