tests for separated connection

This commit is contained in:
brianc 2010-10-23 17:36:04 -05:00
parent 8fa3ce6d1e
commit 5fdf25c31d
6 changed files with 180 additions and 151 deletions

View File

@ -9,14 +9,7 @@ var BufferList = require(__dirname + '/buffer-list');
var Connection = function(config) {
EventEmitter.call(this);
config = config || {};
this.user = config.user;
this.database = config.database;
this.port = config.port || 5432;
this.host = config.host;
this.queryQueue = [];
this.stream = config.stream || new net.Stream();
this.queryQueue = [];
this.password = config.password || '';
this.lastBuffer = false;
this.lastOffset = 0;
this.buffer = null;
@ -28,23 +21,19 @@ sys.inherits(Connection, EventEmitter);
var p = Connection.prototype;
p.connect = function() {
p.connect = function(port, host) {
if(this.stream.readyState === 'closed'){
this.stream.connect(this.port, this.host);
this.stream.connect(port, host);
}else if(this.stream.readyState == 'open') {
this.emit('connect');
}
var self = this;
this.stream.on('connect', function() {
var data = ['user',self.user,'database', self.database, '\0'].join('\0');
var byteLength = Buffer.byteLength(data);
var fullBuffer = new Buffer(byteLength + 4);
fullBuffer[0] = 0;
fullBuffer[1] = 3;
fullBuffer[2] = 0;
fullBuffer[3] = 0;
fullBuffer.write(data, 4);
self.send(null, fullBuffer);
self.emit('connect');
});
this.stream.on('data', function(buffer) {
self.setBuffer(buffer);
var msg;
@ -53,18 +42,18 @@ p.connect = function() {
self.emit(msg.name, msg);
}
});
};
this.on('authenticationCleartextPassword', function() {
self.send('p', new Buffer(self.password + '\0', self.encoding));
});
this.on('authenticationMD5Password', function(msg) {
var enc = function(string) {
return crypto.createHash('md5').update(string).digest('hex');
}
var md5password = "md5" + enc(enc(self.password + self.user) + msg.salt.toString('binary')) + "\0";
self.send('p', new Buffer(md5password, self.encoding));
});
p.startupMessage = function(config) {
var buffer = new BufferList()
.addInt16(3)
.addInt16(0)
.addCString('user')
.addCString(config.user)
.addCString('database')
.addCString(config.database)
.addCString('');
this.send(false, buffer.join());
};
p.send = function(code, bodyBuffer) {
@ -92,7 +81,7 @@ p.end = function() {
};
p.query = function(text) {
this.send('Q', new Buffer(query.text + '\0', this.encoding));
this.send('Q', new Buffer(text + '\0', this.encoding));
};
p.parse = function(query) {
@ -349,4 +338,4 @@ p.parseCString = function() {
return this.buffer.toString(this.encoding, start, this.offset - 1);
};
//end parsing methods
module.exports = Client;
module.exports = Connection;

View File

@ -1,101 +0,0 @@
require(__dirname+'/test-helper');
test('client can take existing stream', function() {
var stream = new MemoryStream();
var client = new Client({
stream: stream
});
assert.equal(client.stream, stream);
});
test('using closed stream', function() {
var stream = new MemoryStream();
stream.readyState = 'closed';
stream.connect = function(port, host) {
this.connectCalled = true;
this.port = port;
this.host = host;
}
var client = new Client({
stream: stream,
user: '!',
database: 'x',
host: 'bang',
port: 1234
});
client.connect();
test('makes stream connect', function() {
assert.equal(stream.connectCalled, true);
});
test('uses configured port', function() {
assert.equal(stream.port, 1234);
});
test('uses configured host', function() {
assert.equal(stream.host, 'bang');
});
test('after stream connects', function() {
stream.emit('connect');
test('sends connection packet', function() {
assert.length(stream.packets, 1);
var expectedBuffer = new BufferList()
.add(Buffer([0,3,0, 0]))//version
.addCString('user')
.addCString('!')
.addCString('database')
.addCString('x')
.addCString("") //final terminator
.join(true);
assert.equalBuffers(stream.packets[0], expectedBuffer);
});
});
});
test('using opened stream', function() {
var stream = new MemoryStream();
stream.readyState = 'open';
stream.connect = function() {
assert.ok(false, "Should not call open");
};
var client = new Client({stream: stream});
test('does not call open', function() {
client.connect();
});
});
test('query queue', function() {
var stream = new MemoryStream();
stream.readyState = 'open';
var client = new Client({
stream: stream
});
client.connect();
test('new client has empty queue', function() {
assert.empty(client.queryQueue);
});
test('calling query queues the query object', function() {
var query = client.query('!');
assert.length(client.queryQueue, 1);
});
test('sends query after stream emits ready for query packet', function() {
assert.empty(stream.packets);
var handled = stream.emit('data', buffers.readyForQuery());
assert.ok(handled, "Stream should have had data handled");
assert.length(stream.packets, 1);
assert.equalBuffers(stream.packets[0], [0x51,0,0,0,6,33,0])
});
});

View File

@ -0,0 +1,89 @@
require(__dirname + "/test-helper");
var stream = new MemoryStream();
var con = new Connection({
stream: stream
});
assert.recieved = function(stream, buffer) {
assert.length(stream.packets, 1);
var packet = stream.packets.pop();
assert.equalBuffers(packet, buffer);
};
test("sends startup message", function() {
con.startupMessage({
user: 'brian',
database: 'bang'
});
assert.recieved(stream, new BufferList()
.addInt16(3)
.addInt16(0)
.addCString('user')
.addCString('brian')
.addCString('database')
.addCString('bang')
.addCString('').join(true))
});
test('sends query message', function() {
var txt = 'select * from boom';
con.query(txt);
assert.recieved(stream, new BufferList().addCString(txt).join(true,'Q'));
});
test('sends parse message', function() {
con.parse({text: '!'});
var expected = new BufferList()
.addCString("")
.addCString("!")
.addInt16(0).join(true, 'P');
assert.recieved(stream, expected);
});
test('sends parse message with named query', function() {
con.parse({
name: 'boom',
text: 'select * from boom',
types: []
});
var expected = new BufferList()
.addCString("boom")
.addCString("select * from boom")
.addInt16(0).join(true,'P');
assert.recieved(stream, expected);
});
test('sends bind to unamed statement with no values', function() {
con.bind();
var expectedBuffer = new BufferList()
.addCString("")
.addCString("")
.addInt16(0)
.addInt16(0)
.addInt16(0).join(true,"B");
assert.recieved(stream, expectedBuffer);
});
test("sends execute message for unamed portal with no row limit", function() {
con.execute();
var expectedBuffer = new BufferList()
.addCString('')
.addInt32(0)
.join(true,'E');
assert.recieved(stream, expectedBuffer);
});
test('sends flush command', function() {
con.flush();
var expected = new BufferList().join(true, 'H');
assert.recieved(stream, expected);
});
test('sends sync command', function() {
con.sync();
var expected = new BufferList().join(true,'S');
assert.recieved(stream, expected);
});

View File

@ -0,0 +1,64 @@
require(__dirname+'/test-helper');
test('connection can take existing stream', function() {
var stream = new MemoryStream();
var con = new Connection({stream: stream});
assert.equal(con.stream, stream);
});
test('using closed stream', function() {
var stream = new MemoryStream();
stream.readyState = 'closed';
stream.connect = function(port, host) {
this.connectCalled = true;
this.port = port;
this.host = host;
}
var con = new Connection({stream: stream});
con.connect(1234, 'bang');
test('makes stream connect', function() {
assert.equal(stream.connectCalled, true);
});
test('uses configured port', function() {
assert.equal(stream.port, 1234);
});
test('uses configured host', function() {
assert.equal(stream.host, 'bang');
});
test('after stream connects client emits connected event', function() {
var hit = false;
con.once('connect', function() {
hit = true;
});
assert.ok(stream.emit('connect'));
assert.ok(hit);
});
});
test('using opened stream', function() {
var stream = new MemoryStream();
stream.readyState = 'open';
stream.connect = function() {
assert.ok(false, "Should not call open");
};
var con = new Connection({stream: stream});
test('does not call open', function() {
var hit = false;
con.once('connect', function() {
hit = true;
});
con.connect();
assert.ok(hit);
});
});

View File

@ -72,20 +72,4 @@ test('prepared queries', function() {
});
test('sends flush command', function() {
client.flush();
assert.length(client.stream.packets, 1);
var packet = client.stream.packets.pop();
var expected = new BufferList().join(true, 'H');
assert.equalBuffers(packet, expected);
});
test('sends sync command', function() {
client.sync();
assert.length(client.stream.packets, 1);
var packet = client.stream.packets.pop();
var expected = new BufferList().join(true,'S');
assert.equalBuffers(packet, expected);
});
});

View File

@ -4,7 +4,7 @@ Client = require(__dirname+'/../../lib/client');
EventEmitter = require('events').EventEmitter;
BufferList = require(__dirname+'/../../lib/buffer-list');
buffers = require(__dirname+'/test-buffers');
Connection = require(__dirname + '/../../lib/connection');
Connection = require(__dirname + '/../../lib/connection')
assert.same = function(actual, expected) {
for(var key in expected) {
assert.equal(actual[key], expected[key]);
@ -46,7 +46,7 @@ test = function(name, action) {
}
}catch(e) {
process.stdout.write('E');
test.errors.push(e);
test.errors.push({name: name, e: e});
}
};
test.testCount = 0;
@ -62,8 +62,12 @@ process.on('exit', function() {
console.log("Ignored: " + name);
});
test.errors.forEach(function(error) {
throw error;
console.log("Error: " + error.name);
});
test.errors.forEach(function(error) {
throw error.e;
});
});
MemoryStream = function() {