Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

V1.0 #301

Merged
merged 6 commits into from

6 participants

@brianc
Owner

This pull request introduces a few breaking changes.

1) Floats will be returned from node-postgres as JavaScript strings instead of being parsed.

Using parseFloat can lead to very tricky and hard to catch rounding & conversion errors within JavaScript. Data loss is the last thing node-postgres should do. If you'd like you can override the float type parsers yourself to either use parseFloat like v0.x or another JavaScript large number library which is better suited to handle larger numeric values.

2) The client pool callback now requires 3 parameters as outlined in the documentation here:

https://github.com/brianc/node-postgres/wiki/pg

if you install pg@1.0 or greater and you do not call the done() callback in pg.connect you will very quickly exhaust the client pool

3) Client#pauseDrain() and Client#resumeDrain() are removed because the pool will no longer automatically return clients when they emit the drain event. Please note the drain event will still be emitted, that did not change. Only now node-postgres itself will not respond to it. Since it doesn't respond to it there's no reason you need to stop it from emitting.

@strk

Will you create a 0.14 branch before merging this ?

@brianc
Owner

yah I will, but I don't plan on maintaining a previous version or "break fix" branch except w/ critical fixes.

@strk
@brianc
Owner

yah definitely will merge those today.

Also, the API breakage is pretty small. It's really just the pool requiring a 3rd parameter when checking out a client and parseFloat not being the default. You can definitely still over-ride the default type parsing and revert it back to using parseFloat if that worked in your apps. That should only take a few lines during app initialization to revert to old behavior.

As for pauseDrain and resumeDrain being removed....those were a travesty to begin with. :blush:

@jmarca

Can you post an example of how to use another library to do the numeric conversion? I found https://github.com/alexbardas/bignumber.js, https://github.com/MikeMcl/bignumber.js, and https://github.com/justmoon/node-bignum.

One fix of course is to turn off parsing and get numbers as strings, then wire one of these libraries (or some other version) to convert numbers from string after they are returned. A cleaner solution would be to write a converter and pass it in somehow. That is what I am asking for documentation on how to do. I don't understand what the register stuff is doing here and I can't find an option setting to insert my own even if I could figure out what is going on there.

@spollack

@brianc: i agree that an example of how to hook parseFloat or similar back up would be great.

related to this, since i am implicitly loading pg via gesundheit/any-db i'm going to need to figure out how to get that custom pg post-initialization code to run...

@brianc
Owner
@brianc brianc merged commit 1d65417 into master
@strk

I'm also interested in the example about reverting to old behavior, it'll be important for everyone upgrading.

@laurentdebricon

I would like to turn on the old behavior

var pg = require('pg');
pg.defaults.parseFloat = true

It doesn't seem to work. Any ideas ?

@mren mren referenced this pull request in snd/mesa
Closed

node-pg requires call to done() method #7

@strk

@laurentdebricon require('pg').types.setTypeParser() something (not documented on the wiki, it seems)

@strk

@brianc still I don't really understand the rationale for dropping support for numbers.
Beside you left support for parsing _float4 _float8 and _numeric (the array types) but drop the single (non-array) type...

@spollack

@brianc I agree with @strk that i don't understand the rationale for dropping support for numbers.

I would imagine that most users of the pg module are going to need to manipulate numeric data, and so having some facility for this (be that mapping to native types, or using a higher level abstraction, or both) built in to the library is important.

(btw, I totally get that postgres and javascript types do not map to each other perfectly. its not just potential loss of precision on floats; its also bigints that may overflow the javascript number, and i'm sure a variety of other examples.)

@brianc
Owner
  1. for reference on why default to parsing floats was removed please see: #271 /cc @shtylman @freewil basically converting from postgres float (or double) to javascript float corrupts your data and you will be none-the-wiser. It's unacceptable as an out of the box default because of the size and impact that footgun has. If you yourself know you're dealing with floats parseFloat can handle you can "opt-in" to use the old behavior. (see point 3)

  2. Whoops, I missed the array parsers. I'll remove those soon.

  3. Today I'm going to build a module you can npm install and use to restore the old behavior to postgres. It will be called pg-parse-float. If you install this and require it anywhere it will patch into postgres and restore the old behavior. This module can also be used as a reference point for providing the various other 3rd party big-number library implementations.

  4. It's easier to detect when ints are going to be stomped by postgres and it's also a lot less common, so that default wasn't changed to strings. I think technically it would be nice to return everything as either a string or null with type information and have other modules includable to provide custom parsers, but that would be horrifically large change at this point, and while "cleaner" wouldn't be more usable. The parseFloat had to go because it was actually broken. If you insert a value and get a different value back...what good at all is your datastore?

@strk
@spollack

@brianc thank you for the detailed response, much appreciated. and definitely looking forward to the pg-parse-float module.

sorry i'm being slow here, but i'm still missing something here as to why this is a giant footgun (great visual image image btw ;-). I ran the test case (https://gist.github.com/shtylman/4757910) referenced in #271, and the results i get back (node 0.8.19) are:
1.79769313486231579
1.7976931348623157
Which doesn't strike me as horrific data loss. particularly if the postgres datatype was real/float4, which only has 6 digits of precision.

@brianc
Owner

You can actually put float values in as strings due to the way the postgres protocol works:

https://github.com/brianc/node-pg-parse-float/blob/master/test.js#L17

@strk it's easier to detect stomped ints because there is Number.MAX_VALUE...except this code has been removed...it used to be here: https://github.com/brianc/node-postgres/blob/master/lib/types/textParsers.js#L159 I should probably add that back in. It would just spit out a warning to the console.

@laurentdebricon et al - I created this module you should be able to use to restore the old behavior in 1 line of code. You can also use it as a reference for making other custom type parsers (i.e. JSON)

https://github.com/brianc/node-pg-parse-float

@defunctzombie
@defunctzombie
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 7, 2013
  1. fix broken test

    authored
  2. remove pauseDrain/resumeDrain

    authored
  3. remove parseFloat

    authored
Commits on Mar 16, 2013
Commits on Mar 17, 2013
This page is out of date. Refresh to see the latest.
Showing with 119 additions and 698 deletions.
  1. +1 −35 lib/client.js
  2. +1 −1  lib/connection.js
  3. +0 −9 lib/defaults.js
  4. +0 −25 lib/deprecate.js
  5. +7 −56 lib/pool.js
  6. +0 −8 lib/types/binaryParsers.js
  7. +1 −31 lib/types/textParsers.js
  8. +0 −128 lib/writer.js
  9. +2 −2 package.json
  10. +2 −1  script/test-connection.js
  11. +18 −14 test/integration/client/api-tests.js
  12. +2 −10 test/integration/client/array-tests.js
  13. +12 −11 test/integration/client/copy-tests.js
  14. +0 −55 test/integration/client/drain-tests.js
  15. +2 −1  test/integration/client/huge-numeric-tests.js
  16. +2 −1  test/integration/client/result-metadata-tests.js
  17. +5 −5 test/integration/client/transaction-tests.js
  18. +8 −7 test/integration/client/type-coercion-tests.js
  19. +2 −1  test/integration/connection-pool/ending-pool-tests.js
  20. +7 −6 test/integration/connection-pool/error-tests.js
  21. +2 −1  test/integration/connection-pool/idle-timeout-tests.js
  22. +2 −1  test/integration/connection-pool/optional-config-tests.js
  23. +37 −14 test/test-helper.js
  24. +0 −60 test/unit/client/query-queue-tests.js
  25. +3 −3 test/unit/client/typed-query-results-tests.js
  26. +3 −16 test/unit/pool/basic-tests.js
  27. +0 −196 test/unit/writer-tests.js
View
36 lib/client.js
@@ -10,8 +10,6 @@ var Connection = require(__dirname + '/connection');
var CopyFromStream = require(__dirname + '/copystream').CopyFromStream;
var CopyToStream = require(__dirname + '/copystream').CopyToStream;
-var deprecate = require('deprecate');
-
var Client = function(config) {
EventEmitter.call(this);
@@ -205,13 +203,7 @@ Client.prototype._pulseQueryQueue = function() {
this.activeQuery.submit(this.connection);
} else if(this.hasExecuted) {
this.activeQuery = null;
- //TODO remove pauseDrain for v1.0
- if(this._drainPaused > 0) {
- this._drainPaused++;
- }
- else {
- this.emit('drain');
- }
+ this.emit('drain');
}
}
};
@@ -255,32 +247,6 @@ Client.prototype.query = function(config, values, callback) {
return query;
};
-//prevents client from otherwise emitting 'drain' event until 'resumeDrain' is
-//called
-Client.prototype.pauseDrain = function() {
- deprecate('Client.prototype.pauseDrain is deprecated and will be removed it v1.0.0 (very soon)',
- 'please see the following for more details:',
- 'https://github.com/brianc/node-postgres/wiki/pg',
- 'https://github.com/brianc/node-postgres/issues/227',
- 'https://github.com/brianc/node-postgres/pull/274',
- 'feel free to get in touch via github if you have questions');
- this._drainPaused = 1;
-};
-
-//resume raising 'drain' event
-Client.prototype.resumeDrain = function() {
- deprecate('Client.prototype.resumeDrain is deprecated and will be removed it v1.0.0 (very soon)',
- 'please see the following for more details:',
- 'https://github.com/brianc/node-postgres/wiki/pg',
- 'https://github.com/brianc/node-postgres/issues/227',
- 'https://github.com/brianc/node-postgres/pull/274',
- 'feel free to get in touch via github if you have questions');
- if(this._drainPaused > 1) {
- this.emit('drain');
- }
- this._drainPaused = 0;
-};
-
Client.prototype.end = function() {
this.connection.end();
};
View
2  lib/connection.js
@@ -4,7 +4,7 @@ var EventEmitter = require('events').EventEmitter;
var util = require('util');
var utils = require(__dirname + '/utils');
-var Writer = require(__dirname + '/writer');
+var Writer = require('buffer-writer');
var Connection = function(config) {
EventEmitter.call(this);
View
9 lib/defaults.js
@@ -33,12 +33,3 @@ module.exports = {
//pool log function / boolean
poolLog: false
};
-
-var deprecate = require('deprecate');
-//getter/setter to disable deprecation warnings
-module.exports.__defineGetter__("hideDeprecationWarnings", function() {
- return deprecate.silent;
-});
-module.exports.__defineSetter__("hideDeprecationWarnings", function(val) {
- deprecate.silence = val;
-});
View
25 lib/deprecate.js
@@ -1,25 +0,0 @@
-var os = require('os');
-var defaults = require(__dirname + '/defaults');
-
-var hits = {
-};
-var deprecate = module.exports = function(methodName, message) {
- if(defaults.hideDeprecationWarnings) return;
- if(hits[deprecate.caller]) return;
- hits[deprecate.caller] = true;
- process.stderr.write(os.EOL);
- process.stderr.write('\x1b[31;1m');
- process.stderr.write('WARNING!!');
- process.stderr.write(os.EOL);
- process.stderr.write(methodName);
- process.stderr.write(os.EOL);
- for(var i = 1; i < arguments.length; i++) {
- process.stderr.write(arguments[i]);
- process.stderr.write(os.EOL);
- }
- process.stderr.write('\x1b[0m');
- process.stderr.write(os.EOL);
- process.stderr.write("You can silence these warnings with `require('pg').defaults.hideDeprecationWarnings = true`");
- process.stderr.write(os.EOL);
- process.stderr.write(os.EOL);
-};
View
63 lib/pool.js
@@ -3,8 +3,6 @@ var EventEmitter = require('events').EventEmitter;
var defaults = require(__dirname + '/defaults');
var genericPool = require('generic-pool');
-var deprecate = require('deprecate');
-
var pools = {
//dictionary of all key:pool pairs
all: {},
@@ -54,64 +52,17 @@ var pools = {
pool.connect = function(cb) {
pool.acquire(function(err, client) {
if(err) return cb(err, null, function() {/*NOOP*/});
- //support both 2 (old) and 3 arguments
- (cb.length > 2 ? newConnect : oldConnect)(pool, client, cb);
+ cb(null, client, function(err) {
+ if(err) {
+ pool.destroy(client);
+ } else {
+ pool.release(client);
+ }
+ });
});
};
return pool;
}
};
-//the old connect method of the pool
-//would automatically subscribe to the 'drain'
-//event and automatically return the client to
-//the pool once 'drain' fired once. This caused
-//a bunch of problems, but for backwards compatibility
-//we're leaving it in
-var alarmDuration = 5000;
-var errorMessage = [
- 'A client has been checked out from the pool for longer than ' + alarmDuration + ' ms.',
- 'You might have a leak!',
- 'You should use the following new way to check out clients','pg.connect(function(err, client, done)) {',
- ' //do something',
- ' done(); //call done() to signal you are finished with the client',
- '}'
-].join(require('os').EOL);
-
-var oldConnect = function(pool, client, cb) {
- deprecate('pg.connect(function(err, client) { ...}) is deprecated and will be removed it v1.0.0 (very soon)',
- 'instead, use pg.connect(function(err, client, done) { ... })',
- 'automatic releasing of clients back to the pool was a mistake and will be removed',
- 'please see the following for more details:',
- 'https://github.com/brianc/node-postgres/wiki/pg',
- 'https://github.com/brianc/node-postgres/issues/227',
- 'https://github.com/brianc/node-postgres/pull/274',
- 'feel free to get in touch via github if you have questions');
- var tid = setTimeout(function() {
- console.error(errorMessage);
- }, alarmDuration);
- var onError = function() {
- clearTimeout(tid);
- client.removeListener('drain', release);
- };
- var release = function() {
- clearTimeout(tid);
- pool.release(client);
- client.removeListener('error', onError);
- };
- client.once('drain', release);
- client.once('error', onError);
- cb(null, client);
-};
-
-var newConnect = function(pool, client, cb) {
- cb(null, client, function(err) {
- if(err) {
- pool.destroy(client);
- } else {
- pool.release(client);
- }
- });
-};
-
module.exports = pools;
View
8 lib/types/binaryParsers.js
@@ -1,5 +1,3 @@
-var deprecate = require('deprecate');
-
var parseBits = function(data, bits, offset, invert, callback) {
offset = offset || 0;
invert = invert || false;
@@ -47,12 +45,6 @@ var parseBits = function(data, bits, offset, invert, callback) {
};
var parseFloatFromBits = function(data, precisionBits, exponentBits) {
- deprecate('parsing and returning floats from PostgreSQL server is deprecated',
- 'JavaScript has a hard time with floats and there is precision loss which can cause',
- 'unexpected, hard to trace, potentially bad bugs in your program',
- 'for more information see the following:',
- 'https://github.com/brianc/node-postgres/pull/271',
- 'in node-postgres v1.0.0 all floats & decimals will be returned as strings');
var bias = Math.pow(2, exponentBits - 1) - 1;
var sign = parseBits(data, 1);
var exponent = parseBits(data, exponentBits, 1);
View
32 lib/types/textParsers.js
@@ -1,5 +1,3 @@
-var deprecate = require('deprecate');
-
var arrayParser = require(__dirname + "/arrayParser.js");
//parses PostgreSQL server formatted date strings into javascript date objects
@@ -78,18 +76,8 @@ var parseIntegerArray = function(val) {
};
var parseFloatArray = function(val) {
- deprecate('parsing and returning floats from PostgreSQL server is deprecated',
- 'JavaScript has a hard time with floats and there is precision loss which can cause',
- 'unexpected, hard to trace, potentially bad bugs in your program',
- 'for more information see the following:',
- 'https://github.com/brianc/node-postgres/pull/271',
- 'in node-postgres v1.0.0 all floats & decimals will be returned as strings',
- 'feel free to get in touch via a github issue if you have any questions');
if(!val) { return null; }
- var p = arrayParser.create(val, function(entry){
- if(entry !== null) {
- entry = parseFloat(entry, 10);
- }
+ var p = arrayParser.create(val, function(entry) {
return entry;
});
@@ -171,27 +159,11 @@ var parseInteger = function(val) {
return parseInt(val, 10);
};
-var parseFloatAndWarn = function(val) {
- deprecate('parsing and returning floats from PostgreSQL server is deprecated',
- 'JavaScript has a hard time with floats and there is precision loss which can cause',
- 'unexpected, hard to trace, potentially bad bugs in your program',
- 'for more information see the following:',
- 'https://github.com/brianc/node-postgres/pull/271',
- 'in node-postgres v1.0.0 all floats & decimals will be returned as strings');
- return parseFloat(val);
-};
-
var init = function(register) {
register(20, parseInteger);
register(21, parseInteger);
register(23, parseInteger);
register(26, parseInteger);
- //TODO remove for v1.0
- register(1700, parseFloatAndWarn);
- //TODO remove for v1.0
- register(700, parseFloatAndWarn);
- //TODO remove for v1.0
- register(701, parseFloatAndWarn);
register(16, parseBool);
register(1082, parseDate); // date
register(1114, parseDate); // timestamp without timezone
@@ -199,8 +171,6 @@ var init = function(register) {
register(1005, parseIntegerArray); // _int2
register(1007, parseIntegerArray); // _int4
register(1016, parseIntegerArray); // _int8
- register(1021, parseFloatArray); // _float4
- register(1022, parseFloatArray); // _float8
register(1231, parseIntegerArray); // _numeric
register(1014, parseStringArray); //char
register(1015, parseStringArray); //varchar
View
128 lib/writer.js
@@ -1,128 +0,0 @@
-//binary data writer tuned for creating
-//postgres message packets as effeciently as possible by reusing the
-//same buffer to avoid memcpy and limit memory allocations
-var Writer = function(size) {
- this.size = size || 1024;
- this.buffer = Buffer(this.size + 5);
- this.offset = 5;
- this.headerPosition = 0;
-};
-
-//resizes internal buffer if not enough size left
-Writer.prototype._ensure = function(size) {
- var remaining = this.buffer.length - this.offset;
- if(remaining < size) {
- var oldBuffer = this.buffer;
- this.buffer = new Buffer(oldBuffer.length + size);
- oldBuffer.copy(this.buffer);
- }
-};
-
-Writer.prototype.addInt32 = function(num) {
- this._ensure(4);
- this.buffer[this.offset++] = (num >>> 24 & 0xFF);
- this.buffer[this.offset++] = (num >>> 16 & 0xFF);
- this.buffer[this.offset++] = (num >>> 8 & 0xFF);
- this.buffer[this.offset++] = (num >>> 0 & 0xFF);
- return this;
-};
-
-Writer.prototype.addInt16 = function(num) {
- this._ensure(2);
- this.buffer[this.offset++] = (num >>> 8 & 0xFF);
- this.buffer[this.offset++] = (num >>> 0 & 0xFF);
- return this;
-};
-
-//for versions of node requiring 'length' as 3rd argument to buffer.write
-var writeString = function(buffer, string, offset, len) {
- buffer.write(string, offset, len);
-};
-
-//overwrite function for older versions of node
-if(Buffer.prototype.write.length === 3) {
- writeString = function(buffer, string, offset, len) {
- buffer.write(string, offset);
- };
-}
-
-Writer.prototype.addCString = function(string) {
- //just write a 0 for empty or null strings
- if(!string) {
- this._ensure(1);
- } else {
- var len = Buffer.byteLength(string);
- this._ensure(len + 1); //+1 for null terminator
- writeString(this.buffer, string, this.offset, len);
- this.offset += len;
- }
-
- this.buffer[this.offset++] = 0; // null terminator
- return this;
-};
-
-Writer.prototype.addChar = function(c) {
- this._ensure(1);
- writeString(this.buffer, c, this.offset, 1);
- this.offset++;
- return this;
-};
-
-Writer.prototype.addString = function(string) {
- string = string || "";
- var len = Buffer.byteLength(string);
- this._ensure(len);
- this.buffer.write(string, this.offset);
- this.offset += len;
- return this;
-};
-
-Writer.prototype.getByteLength = function() {
- return this.offset - 5;
-};
-
-Writer.prototype.add = function(otherBuffer) {
- this._ensure(otherBuffer.length);
- otherBuffer.copy(this.buffer, this.offset);
- this.offset += otherBuffer.length;
- return this;
-};
-
-Writer.prototype.clear = function() {
- this.offset = 5;
- this.headerPosition = 0;
- this.lastEnd = 0;
-};
-
-//appends a header block to all the written data since the last
-//subsequent header or to the beginning if there is only one data block
-Writer.prototype.addHeader = function(code, last) {
- var origOffset = this.offset;
- this.offset = this.headerPosition;
- this.buffer[this.offset++] = code;
- //length is everything in this packet minus the code
- this.addInt32(origOffset - (this.headerPosition+1));
- //set next header position
- this.headerPosition = origOffset;
- //make space for next header
- this.offset = origOffset;
- if(!last) {
- this._ensure(5);
- this.offset += 5;
- }
-};
-
-Writer.prototype.join = function(code) {
- if(code) {
- this.addHeader(code, true);
- }
- return this.buffer.slice(code ? 0 : 5, this.offset);
-};
-
-Writer.prototype.flush = function(code) {
- var result = this.join(code);
- this.clear();
- return result;
-};
-
-module.exports = Writer;
View
4 package.json
@@ -1,6 +1,6 @@
{
"name": "pg",
- "version": "0.14.0",
+ "version": "1.0.0",
"description": "PostgreSQL client - pure javascript & libpq with the same API",
"keywords": [
"postgres",
@@ -19,7 +19,7 @@
"main": "./lib",
"dependencies": {
"generic-pool": "2.0.2",
- "deprecate": "~0.1.0"
+ "buffer-writer": "1.0.0"
},
"devDependencies": {
"jshint": "git://github.com/jshint/jshint.git"
View
3  script/test-connection.js
@@ -3,7 +3,7 @@ var helper = require(__dirname + '/../test/test-helper');
console.log();
console.log("testing ability to connect to '%j'", helper.config);
var pg = require(__dirname + '/../lib');
-pg.connect(helper.config, function(err, client) {
+pg.connect(helper.config, function(err, client, done) {
if(err !== null) {
console.error("Recieved connection error when attempting to contact PostgreSQL:");
console.error(err);
@@ -18,6 +18,7 @@ pg.connect(helper.config, function(err, client) {
console.error(err);
process.exit(255);
}
+ done();
pg.end();
})
})
View
32 test/integration/client/api-tests.js
@@ -1,9 +1,5 @@
var helper = require(__dirname + '/../test-helper');
-var pg = require(__dirname + '/../../../lib');
-
-if(helper.args.native) {
- pg = require(__dirname + '/../../../lib').native;
-}
+var pg = helper.pg;
var log = function() {
//console.log.apply(console, arguments);
@@ -20,8 +16,9 @@ test('api', function() {
pg.connect(helper.config, function(err) {
assert.isNull(err);
arguments[1].emit('drain');
+ arguments[2]();
});
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.equal(err, null, "Failed to connect: " + helper.sys.inspect(err));
client.query('CREATE TEMP TABLE band(name varchar(100))');
@@ -56,14 +53,14 @@ test('api', function() {
assert.equal(result.rows.pop().name, 'the flaming lips');
assert.equal(result.rows.pop().name, 'the beach boys');
sink.add();
+ done();
}))
}))
-
}))
})
test('executing nested queries', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
log("connected for nested queriese")
client.query('select now as now from NOW()', assert.calls(function(err, result) {
@@ -73,6 +70,7 @@ test('executing nested queries', function() {
log('all nested queries recieved')
assert.ok('all queries hit')
sink.add();
+ done();
}))
}))
}))
@@ -82,27 +80,29 @@ test('executing nested queries', function() {
test('raises error if cannot connect', function() {
var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie";
log("trying to connect to invalid place for error")
- pg.connect(connectionString, assert.calls(function(err, client) {
+ pg.connect(connectionString, assert.calls(function(err, client, done) {
assert.ok(err, 'should have raised an error')
log("invalid connection supplied error to callback")
sink.add();
+ done();
}))
})
test("query errors are handled and do not bubble if callback is provded", function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err)
log("checking for query error")
client.query("SELECT OISDJF FROM LEIWLISEJLSE", assert.calls(function(err, result) {
assert.ok(err);
log("query error supplied error to callback")
sink.add();
+ done();
}))
}))
})
test('callback is fired once and only once', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query("CREATE TEMP TABLE boom(name varchar(10))");
var callCount = 0;
@@ -113,12 +113,13 @@ test('callback is fired once and only once', function() {
].join(";"), function(err, callback) {
assert.equal(callCount++, 0, "Call count should be 0. More means this callback fired more than once.");
sink.add();
+ done();
})
}))
})
test('can provide callback and config object', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query({
name: 'boom',
@@ -126,12 +127,13 @@ test('can provide callback and config object', function() {
}, assert.calls(function(err, result) {
assert.isNull(err);
assert.equal(result.rows[0].now.getYear(), new Date().getYear())
+ done();
}))
}))
})
test('can provide callback and config and parameters', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
var config = {
text: 'select $1::text as val'
@@ -140,12 +142,13 @@ test('can provide callback and config and parameters', function() {
assert.isNull(err);
assert.equal(result.rows.length, 1);
assert.equal(result.rows[0].val, 'hi');
+ done();
}))
}))
})
test('null and undefined are both inserted as NULL', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query("CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)");
client.query("INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)", [ null, undefined, null, undefined, null, undefined ]);
@@ -158,6 +161,7 @@ test('null and undefined are both inserted as NULL', function() {
assert.isNull(result.rows[0].d);
assert.isNull(result.rows[0].e);
assert.isNull(result.rows[0].f);
+ done();
}))
}))
})
View
12 test/integration/client/array-tests.js
@@ -2,7 +2,7 @@ var helper = require(__dirname + "/test-helper");
var pg = helper.pg;
test('parsing array results', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query("CREATE TEMP TABLE why(names text[], numbors integer[])");
client.query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')').on('error', console.log);
@@ -23,7 +23,6 @@ test('parsing array results', function() {
assert.equal(names[0], 'aaron');
assert.equal(names[1], 'brian');
assert.equal(names[2], "a b c");
- pg.end();
}))
})
@@ -31,7 +30,6 @@ test('parsing array results', function() {
client.query("SELECT '{}'::text[] as names", assert.success(function(result) {
var names = result.rows[0].names;
assert.lengthIs(names, 0);
- pg.end();
}))
})
@@ -41,7 +39,6 @@ test('parsing array results', function() {
assert.lengthIs(names, 2);
assert.equal(names[0], 'joe,bob');
assert.equal(names[1], 'jim');
- pg.end();
}))
})
@@ -51,7 +48,6 @@ test('parsing array results', function() {
assert.lengthIs(names, 2);
assert.equal(names[0], '{');
assert.equal(names[1], '}');
- pg.end();
}))
})
@@ -63,7 +59,6 @@ test('parsing array results', function() {
assert.equal(names[1], null);
assert.equal(names[2], 'bob');
assert.equal(names[3], 'NULL');
- pg.end();
}))
})
@@ -74,7 +69,6 @@ test('parsing array results', function() {
assert.equal(names[0], 'joe\'');
assert.equal(names[1], 'jim');
assert.equal(names[2], 'bob"');
- pg.end();
}))
})
@@ -91,7 +85,6 @@ test('parsing array results', function() {
assert.equal(names[1][0], '2');
assert.equal(names[1][1], 'bob');
- pg.end();
}))
})
@@ -102,7 +95,6 @@ test('parsing array results', function() {
assert.equal(names[0], 1);
assert.equal(names[1], 2);
assert.equal(names[2], 3);
- pg.end();
}))
})
@@ -118,7 +110,6 @@ test('parsing array results', function() {
assert.equal(names[2][0], 3);
assert.equal(names[2][1], 100);
- pg.end();
}))
})
@@ -134,6 +125,7 @@ test('parsing array results', function() {
assert.equal(names[2][0], 3);
assert.equal(names[2][1], 100);
+ done();
pg.end();
}))
})
View
23 test/integration/client/copy-tests.js
@@ -14,7 +14,7 @@ var prepareTable = function (client, callback) {
);
};
test('COPY FROM', function () {
- pg.connect(helper.config, function (error, client) {
+ pg.connect(helper.config, function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
prepareTable(client, function () {
var stream = client.copyFrom("COPY copy_test (name, age) FROM stdin WITH CSV");
@@ -30,7 +30,7 @@ test('COPY FROM', function () {
assert.lengthIs(result.rows, 1)
assert.equal(result.rows[0].sum, ROWS_TO_INSERT * (0 + ROWS_TO_INSERT -1)/2);
assert.equal(result.rows[0].count, ROWS_TO_INSERT);
- pg.end(helper.config);
+ done();
});
}, "COPY FROM stream should emit close after query end");
stream.end();
@@ -38,7 +38,7 @@ test('COPY FROM', function () {
});
});
test('COPY TO', function () {
- pg.connect(helper.config, function (error, client) {
+ pg.connect(helper.config, function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
prepareTable(client, function () {
var stream = client.copyTo("COPY person (id, name, age) TO stdin WITH CSV");
@@ -53,7 +53,7 @@ test('COPY TO', function () {
var lines = buf.toString().split('\n');
assert.equal(lines.length >= 0, true, "copy in should return rows saved by copy from");
assert.equal(lines[0].split(',').length, 3, "each line should consists of 3 fields");
- pg.end(helper.config);
+ done();
}, "COPY IN stream should emit end event after all rows");
});
});
@@ -61,7 +61,7 @@ test('COPY TO', function () {
test('COPY TO, queue queries', function () {
if(helper.config.native) return false;
- pg.connect(helper.config, assert.calls(function (error, client) {
+ pg.connect(helper.config, assert.calls(function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
prepareTable(client, function () {
var query1Done = false,
@@ -92,7 +92,7 @@ test('COPY TO, queue queries', function () {
var lines = buf.toString().split('\n');
assert.equal(lines.length >= 0, true, "copy in should return rows saved by copy from");
assert.equal(lines[0].split(',').length, 3, "each line should consists of 3 fields");
- pg.end(helper.config);
+ done();
}, "COPY IN stream should emit end event after all rows");
});
}));
@@ -105,7 +105,7 @@ test("COPY TO incorrect usage with large data", function () {
//but if there are not so much data, cancel message may be
//send after copy query ends
//so we need to test both situations
- pg.connect(helper.config, assert.calls(function (error, client) {
+ pg.connect(helper.config, assert.calls(function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
//intentionally incorrect usage of copy.
//this has to report error in standart way, instead of just throwing exception
@@ -116,7 +116,7 @@ test("COPY TO incorrect usage with large data", function () {
client.query("SELECT 1", assert.calls(function (error, result) {
assert.isNull(error, "incorrect copy usage should not break connection");
assert.ok(result, "incorrect copy usage should not break connection");
- pg.end(helper.config);
+ done();
}));
})
);
@@ -125,7 +125,7 @@ test("COPY TO incorrect usage with large data", function () {
test("COPY TO incorrect usage with small data", function () {
if(helper.config.native) return false;
- pg.connect(helper.config, assert.calls(function (error, client) {
+ pg.connect(helper.config, assert.calls(function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
//intentionally incorrect usage of copy.
//this has to report error in standart way, instead of just throwing exception
@@ -136,7 +136,7 @@ test("COPY TO incorrect usage with small data", function () {
client.query("SELECT 1", assert.calls(function (error, result) {
assert.isNull(error, "incorrect copy usage should not break connection");
assert.ok(result, "incorrect copy usage should not break connection");
- pg.end(helper.config);
+ done();
}));
})
);
@@ -144,7 +144,7 @@ test("COPY TO incorrect usage with small data", function () {
});
test("COPY FROM incorrect usage", function () {
- pg.connect(helper.config, function (error, client) {
+ pg.connect(helper.config, function (error, client, done) {
assert.equal(error, null, "Failed to connect: " + helper.sys.inspect(error));
prepareTable(client, function () {
//intentionally incorrect usage of copy.
@@ -156,6 +156,7 @@ test("COPY FROM incorrect usage", function () {
client.query("SELECT 1", assert.calls(function (error, result) {
assert.isNull(error, "incorrect copy usage should not break connection");
assert.ok(result, "incorrect copy usage should not break connection");
+ done();
pg.end(helper.config);
}));
})
View
55 test/integration/client/drain-tests.js
@@ -1,55 +0,0 @@
-var helper = require(__dirname + '/test-helper');
-var pg = require(__dirname + '/../../../lib');
-
-if(helper.args.native) {
- pg = require(__dirname + '/../../../lib').native;
-}
-
-var testDrainOfClientWithPendingQueries = function() {
- pg.connect(helper.config, assert.success(function(client) {
- test('when there are pending queries and client is resumed', function() {
- var drainCount = 0;
- client.on('drain', function() {
- drainCount++;
- });
- client.pauseDrain();
- client.query('SELECT NOW()', function() {
- client.query('SELECT NOW()', function() {
- assert.equal(drainCount, 0);
- process.nextTick(function() {
- assert.equal(drainCount, 1);
- pg.end();
- });
- });
- client.resumeDrain();
- assert.equal(drainCount, 0);
- });
- });
- }));
-};
-
-pg.connect(helper.config, assert.success(function(client) {
- var drainCount = 0;
- client.on('drain', function() {
- drainCount++;
- });
- test('pauseDrain and resumeDrain on simple client', function() {
- client.pauseDrain();
- client.resumeDrain();
- process.nextTick(assert.calls(function() {
- assert.equal(drainCount, 0);
- test('drain is paused', function() {
- client.pauseDrain();
- client.query('SELECT NOW()', assert.success(function() {
- process.nextTick(function() {
- assert.equal(drainCount, 0);
- client.resumeDrain();
- assert.equal(drainCount, 1);
- testDrainOfClientWithPendingQueries();
- });
- }));
- });
- }));
- });
-}));
-
View
3  test/integration/client/huge-numeric-tests.js
@@ -1,6 +1,6 @@
var helper = require(__dirname + '/test-helper');
-helper.pg.connect(helper.config, assert.success(function(client) {
+helper.pg.connect(helper.config, assert.success(function(client, done) {
var types = require(__dirname + '/../../../lib/types');
//1231 = numericOID
types.setTypeParser(1700, function(){
@@ -15,6 +15,7 @@ helper.pg.connect(helper.config, assert.success(function(client) {
client.query('SELECT * FROM bignumz', assert.success(function(result) {
assert.equal(result.rows[0].id, 'yes')
helper.pg.end();
+ done();
}))
}));
View
3  test/integration/client/result-metadata-tests.js
@@ -2,7 +2,7 @@ var helper = require(__dirname + "/test-helper");
var pg = helper.pg;
test('should return insert metadata', function() {
- pg.connect(helper.config, assert.calls(function(err, client) {
+ pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) {
@@ -25,6 +25,7 @@ test('should return insert metadata', function() {
assert.emits(q, 'end', function(result) {
assert.equal(result.command, "INSERT");
assert.equal(result.rowCount, 1);
+ done();
});
}));
View
10 test/integration/client/transaction-tests.js
@@ -5,8 +5,7 @@ var sink = new helper.Sink(2, function() {
});
test('a single connection transaction', function() {
- helper.pg.connect(helper.config, assert.calls(function(err, client) {
- assert.isNull(err);
+ helper.pg.connect(helper.config, assert.success(function(client, done) {
client.query('begin');
@@ -39,6 +38,7 @@ test('a single connection transaction', function() {
client.query(getZed, assert.calls(function(err, result) {
assert.isNull(err);
assert.empty(result.rows);
+ done();
sink.add();
}))
})
@@ -46,8 +46,7 @@ test('a single connection transaction', function() {
})
test('gh#36', function() {
- helper.pg.connect(helper.config, function(err, client) {
- if(err) throw err;
+ helper.pg.connect(helper.config, assert.success(function(client, done) {
client.query("BEGIN");
client.query({
name: 'X',
@@ -67,6 +66,7 @@ test('gh#36', function() {
}))
client.query("COMMIT", function() {
sink.add();
+ done();
})
- })
+ }));
})
View
15 test/integration/client/type-coercion-tests.js
@@ -2,7 +2,7 @@ var helper = require(__dirname + '/test-helper');
var sink;
var testForTypeCoercion = function(type){
- helper.pg.connect(helper.config, function(err, client) {
+ helper.pg.connect(helper.config, function(err, client, done) {
assert.isNull(err);
client.query("create temp table test_type(col " + type.name + ")", assert.calls(function(err, result) {
assert.isNull(err);
@@ -31,6 +31,7 @@ var testForTypeCoercion = function(type){
client.query('drop table test_type', function() {
sink.add();
+ done();
});
})
}));
@@ -56,15 +57,14 @@ var types = [{
name: 'bool',
values: [true, false, null]
},{
- //TODO get some actual huge numbers here
name: 'numeric',
- values: [-12.34, 0, 12.34, null]
+ values: ['-12.34', '0', '12.34', null]
},{
name: 'real',
- values: [101.1, 0, -101.3, null]
+ values: ['101.1', '0', '-101.3', null]
},{
name: 'double precision',
- values: [-1.2, 0, 1.2, null]
+ values: ['-1.2', '0', '1.2', null]
},{
name: 'timestamptz',
values: [null]
@@ -82,7 +82,7 @@ var types = [{
// ignore some tests in binary mode
if (helper.config.binary) {
types = types.filter(function(type) {
- return !(type.name in {'real':1, 'timetz':1, 'time':1});
+ return !(type.name in {'real':1, 'timetz':1, 'time':1, 'numeric': 1, 'double precision': 1});
});
}
@@ -133,7 +133,7 @@ test("timestampz round trip", function() {
client.on('drain', client.end.bind(client));
});
-helper.pg.connect(helper.config, assert.calls(function(err, client) {
+helper.pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query('select null as res;', assert.calls(function(err, res) {
assert.isNull(err);
@@ -143,6 +143,7 @@ helper.pg.connect(helper.config, assert.calls(function(err, client) {
assert.isNull(err);
assert.strictEqual(res.rows[0].res, null);
sink.add();
+ done();
})
}))
View
3  test/integration/connection-pool/ending-pool-tests.js
@@ -8,12 +8,13 @@ test('disconnects', function() {
helper.pg.end();
});
[helper.config, helper.config, helper.config, helper.config].forEach(function(config) {
- helper.pg.connect(config, function(err, client) {
+ helper.pg.connect(config, function(err, client, done) {
assert.isNull(err);
client.query("SELECT * FROM NOW()", function(err, result) {
process.nextTick(function() {
assert.equal(called, false, "Should not have disconnected yet")
sink.add();
+ done();
})
})
})
View
13 test/integration/connection-pool/error-tests.js
@@ -1,28 +1,29 @@
var helper = require(__dirname + "/../test-helper");
var pg = require(__dirname + "/../../../lib");
-helper.pg = pg;
+pg = pg;
//first make pool hold 2 clients
-helper.pg.defaults.poolSize = 2;
+pg.defaults.poolSize = 2;
var killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE \'<IDLE>\'';
//get first client
-helper.pg.connect(helper.config, assert.success(function(client) {
+pg.connect(helper.config, assert.success(function(client, done) {
client.id = 1;
- helper.pg.connect(helper.config, assert.success(function(client2) {
+ pg.connect(helper.config, assert.success(function(client2, done2) {
client2.id = 2;
+ done2();
//subscribe to the pg error event
- assert.emits(helper.pg, 'error', function(error, brokenClient) {
+ assert.emits(pg, 'error', function(error, brokenClient) {
assert.ok(error);
assert.ok(brokenClient);
assert.equal(client.id, brokenClient.id);
- helper.pg.end();
});
//kill the connection from client
client2.query(killIdleQuery, assert.success(function(res) {
//check to make sure client connection actually was killed
assert.lengthIs(res.rows, 1);
+ pg.end();
}));
}));
}));
View
3  test/integration/connection-pool/idle-timeout-tests.js
@@ -3,10 +3,11 @@ var helper = require(__dirname + '/test-helper');
helper.pg.defaults.poolIdleTimeout = 200;
test('idle timeout', function() {
- helper.pg.connect(helper.config, assert.calls(function(err, client) {
+ helper.pg.connect(helper.config, assert.calls(function(err, client, done) {
assert.isNull(err);
client.query('SELECT NOW()');
//just let this one time out
//test will hang if pool doesn't timeout
+ done();
}));
});
View
3  test/integration/connection-pool/optional-config-tests.js
@@ -8,12 +8,13 @@ helper.pg.defaults.port = helper.args.port;
helper.pg.defaults.database = helper.args.database;
helper.pg.defaults.poolSize = 1;
-helper.pg.connect(assert.calls(function(err, client) {
+helper.pg.connect(assert.calls(function(err, client, done) {
assert.isNull(err);
client.query('SELECT NOW()');
client.once('drain', function() {
setTimeout(function() {
helper.pg.end();
+ done();
}, 10);
});
View
51 test/test-helper.js
@@ -7,8 +7,6 @@ var BufferList = require(__dirname+'/buffer-list')
var Connection = require(__dirname + '/../lib/connection');
-require(__dirname + '/../lib').defaults.hideDeprecationWarnings = true;
-
Client = require(__dirname + '/../lib').Client;
process.on('uncaughtException', function(d) {
@@ -98,13 +96,25 @@ assert.empty = function(actual) {
};
assert.success = function(callback) {
- return assert.calls(function(err, arg) {
- if(err) {
- console.log(err);
- }
- assert.isNull(err);
- callback(arg);
- })
+ if(callback.length === 1) {
+ return assert.calls(function(err, arg) {
+ if(err) {
+ console.log(err);
+ }
+ assert.isNull(err);
+ callback(arg);
+ });
+ } else if (callback.length === 2) {
+ return assert.calls(function(err, arg1, arg2) {
+ if(err) {
+ console.log(err);
+ }
+ assert.isNull(err);
+ callback(arg1, arg2);
+ });
+ } else {
+ throw new Error('need to preserve arrity of wrapped function');
+ }
}
assert.throws = function(offender) {
@@ -127,13 +137,26 @@ var expect = function(callback, timeout) {
assert.ok(executed, "Expected execution of function to be fired");
}, timeout || 5000)
- return function(err, queryResult) {
- clearTimeout(id);
- if (err) {
- assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err));
+ if(callback.length < 3) {
+ return function(err, queryResult) {
+ clearTimeout(id);
+ if (err) {
+ assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err));
+ }
+ callback.apply(this, arguments)
}
- callback.apply(this, arguments)
+ } else if(callback.length == 3) {
+ return function(err, arg1, arg2) {
+ clearTimeout(id);
+ if (err) {
+ assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err));
+ }
+ callback.apply(this, arguments)
+ }
+ } else {
+ throw new Error("Unsupported arrity " + callback.length);
}
+
}
assert.calls = expect;
View
60 test/unit/client/query-queue-tests.js
@@ -50,63 +50,3 @@ test('drain', function() {
});
});
});
-
-test('with drain paused', function() {
- //mock out a fake connection
- var con = new Connection({stream: "NO"});
- con.connect = function() {
- con.emit('connect');
- };
- con.query = function() {
- };
-
- var client = new Client({connection:con});
-
- client.connect();
-
- var drainCount = 0;
- client.on('drain', function() {
- drainCount++;
- });
-
- test('normally unpaused', function() {
- con.emit('readyForQuery');
- client.query('boom');
- assert.emits(client, 'drain', function() {
- assert.equal(drainCount, 1);
- });
- con.emit('readyForQuery');
- });
-
- test('pausing', function() {
- test('unpaused with no queries in between', function() {
- client.pauseDrain();
- client.resumeDrain();
- assert.equal(drainCount, 1);
- });
-
- test('paused', function() {
- test('resumeDrain after empty', function() {
- client.pauseDrain();
- client.query('asdf');
- con.emit('readyForQuery');
- assert.equal(drainCount, 1);
- client.resumeDrain();
- assert.equal(drainCount, 2);
- });
-
- test('resumDrain while still pending', function() {
- client.pauseDrain();
- client.query('asdf');
- client.query('asdf1');
- con.emit('readyForQuery');
- client.resumeDrain();
- assert.equal(drainCount, 2);
- con.emit('readyForQuery');
- assert.equal(drainCount, 3);
- });
-
- });
- });
-
-});
View
6 test/unit/client/typed-query-results-tests.js
@@ -43,19 +43,19 @@ test('typed results', function() {
format: 'text',
dataTypeID: 1700,
actual: '12.34',
- expected: 12.34
+ expected: '12.34'
},{
name: 'real/float4',
dataTypeID: 700,
format: 'text',
actual: '123.456',
- expected: 123.456
+ expected: '123.456'
},{
name: 'double precision / float8',
format: 'text',
dataTypeID: 701,
actual: '1.2',
- expected: 1.2
+ expected: '1.2'
},{
name: 'boolean true',
format: 'text',
View
19 test/unit/pool/basic-tests.js
@@ -68,19 +68,6 @@ test('pool follows defaults', function() {
assert.equal(p.getPoolSize(), defaults.poolSize);
});
-test('pool#connect with 2 parameters (legacy, for backwards compat)', function() {
- var p = pools.getOrCreate(poolId++);
- p.connect(assert.success(function(client) {
- assert.ok(client);
- assert.equal(p.availableObjectsCount(), 0);
- assert.equal(p.getPoolSize(), 1);
- client.emit('drain');
- assert.equal(p.availableObjectsCount(), 1);
- assert.equal(p.getPoolSize(), 1);
- p.destroyAllNow();
- }));
-});
-
test('pool#connect with 3 parameters', function() {
var p = pools.getOrCreate(poolId++);
var tid = setTimeout(function() {
@@ -88,7 +75,7 @@ test('pool#connect with 3 parameters', function() {
}, 100);
p.connect(function(err, client, done) {
clearTimeout(tid);
- assert.equal(err, null);
+ assert.ifError(err, null);
assert.ok(client);
assert.equal(p.availableObjectsCount(), 0);
assert.equal(p.getPoolSize(), 1);
@@ -104,9 +91,9 @@ test('pool#connect with 3 parameters', function() {
test('on client error, client is removed from pool', function() {
var p = pools.getOrCreate(poolId++);
- p.connect(assert.success(function(client) {
+ p.connect(assert.success(function(client, done) {
assert.ok(client);
- client.emit('drain');
+ done();
assert.equal(p.availableObjectsCount(), 1);
assert.equal(p.getPoolSize(), 1);
//error event fires on pool BEFORE pool.destroy is called with client
View
196 test/unit/writer-tests.js
@@ -1,196 +0,0 @@
-require(__dirname + "/test-helper");
-var Writer = require(__dirname + "/../../lib/writer");
-
-test('adding int32', function() {
- var testAddingInt32 = function(int, expectedBuffer) {
- test('writes ' + int, function() {
- var subject = new Writer();
- var result = subject.addInt32(int).join();
- assert.equalBuffers(result, expectedBuffer);
- })
- }
-
- testAddingInt32(0, [0, 0, 0, 0]);
- testAddingInt32(1, [0, 0, 0, 1]);
- testAddingInt32(256, [0, 0, 1, 0]);
- test('writes largest int32', function() {
- //todo need to find largest int32 when I have internet access
- return false;
- })
-
- test('writing multiple int32s', function() {
- var subject = new Writer();
- var result = subject.addInt32(1).addInt32(10).addInt32(0).join();
- assert.equalBuffers(result, [0, 0, 0, 1, 0, 0, 0, 0x0a, 0, 0, 0, 0]);
- })
-
- test('having to resize the buffer', function() {
- test('after resize correct result returned', function() {
- var subject = new Writer(10);
- subject.addInt32(1).addInt32(1).addInt32(1)
- assert.equalBuffers(subject.join(), [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1])
- })
- })
-})
-
-test('int16', function() {
- test('writes 0', function() {
- var subject = new Writer();
- var result = subject.addInt16(0).join();
- assert.equalBuffers(result, [0,0]);
- })
-
- test('writes 400', function() {
- var subject = new Writer();
- var result = subject.addInt16(400).join();
- assert.equalBuffers(result, [1, 0x90])
- })
-
- test('writes many', function() {
- var subject = new Writer();
- var result = subject.addInt16(0).addInt16(1).addInt16(2).join();
- assert.equalBuffers(result, [0, 0, 0, 1, 0, 2])
- })
-
- test('resizes if internal buffer fills up', function() {
- var subject = new Writer(3);
- var result = subject.addInt16(2).addInt16(3).join();
- assert.equalBuffers(result, [0, 2, 0, 3])
- })
-
-})
-
-test('cString', function() {
- test('writes empty cstring', function() {
- var subject = new Writer();
- var result = subject.addCString().join();
- assert.equalBuffers(result, [0])
- })
-
- test('writes two empty cstrings', function() {
- var subject = new Writer();
- var result = subject.addCString("").addCString("").join();
- assert.equalBuffers(result, [0, 0])
- })
-
-
- test('writes non-empty cstring', function() {
- var subject = new Writer();
- var result = subject.addCString("!!!").join();
- assert.equalBuffers(result, [33, 33, 33, 0]);
- })
-
- test('resizes if reached end', function() {
- var subject = new Writer(3);
- var result = subject.addCString("!!!").join();
- assert.equalBuffers(result, [33, 33, 33, 0]);
- })
-
- test('writes multiple cstrings', function() {
- var subject = new Writer();
- var result = subject.addCString("!").addCString("!").join();
- assert.equalBuffers(result, [33, 0, 33, 0]);
- })
-
-})
-
-test('writes char', function() {
- var subject = new Writer(2);
- var result = subject.addChar('a').addChar('b').addChar('c').join();
- assert.equalBuffers(result, [0x61, 0x62, 0x63])
-})
-
-test('gets correct byte length', function() {
- var subject = new Writer(5);
- assert.equal(subject.getByteLength(), 0)
- subject.addInt32(0)
- assert.equal(subject.getByteLength(), 4)
- subject.addCString("!")
- assert.equal(subject.getByteLength(), 6)
-})
-
-test('can add arbitrary buffer to the end', function() {
- var subject = new Writer(4);
- subject.addCString("!!!")
- var result = subject.add(Buffer("@@@")).join();
- assert.equalBuffers(result, [33, 33, 33, 0, 0x40, 0x40, 0x40]);
-})
-
-test('can write normal string', function() {
- var subject = new Writer(4);
- var result = subject.addString("!").join();
- assert.equalBuffers(result, [33]);
- test('can write cString too', function() {
- var result = subject.addCString("!").join();
- assert.equalBuffers(result, [33, 33, 0]);
- test('can resize', function() {
- var result = subject.addString("!!").join();
- assert.equalBuffers(result, [33, 33, 0, 33, 33]);
- })
-
- })
-
-})
-
-
-test('clearing', function() {
- var subject = new Writer();
- subject.addCString("@!!#!#");
- subject.addInt32(10401);
- subject.clear();
- assert.equalBuffers(subject.join(), []);
- test('can keep writing', function() {
- var joinedResult = subject.addCString("!").addInt32(9).addInt16(2).join();
- assert.equalBuffers(joinedResult, [33, 0, 0, 0, 0, 9, 0, 2]);
- test('flush', function() {
- var flushedResult = subject.flush();
- test('returns result', function() {
- assert.equalBuffers(flushedResult, [33, 0, 0, 0, 0, 9, 0, 2])
- })
- test('clears the writer', function() {
- assert.equalBuffers(subject.join(), [])
- assert.equalBuffers(subject.flush(), [])
- })
- })
- })
-
-})
-
-test("resizing to much larger", function() {
- var subject = new Writer(2);
- var string = "!!!!!!!!";
- var result = subject.addCString(string).flush();
- assert.equalBuffers(result, [33, 33, 33, 33, 33, 33, 33, 33, 0])
-})
-
-test("flush", function() {
- test('added as a hex code to a full writer', function() {
- var subject = new Writer(2);
- var result = subject.addCString("!").flush(0x50)
- assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0]);
- })
-
- test('added as a hex code to a non-full writer', function() {
- var subject = new Writer(10).addCString("!");
- var joinedResult = subject.join(0x50);
- var result = subject.flush(0x50);
- assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0]);
- })
-
- test('added as a hex code to a buffer which requires resizing', function() {
- var result = new Writer(2).addCString("!!!!!!!!").flush(0x50);
- assert.equalBuffers(result, [0x50, 0, 0, 0, 0x0D, 33, 33, 33, 33, 33, 33, 33, 33, 0]);
- })
-})
-
-test("header", function() {
- test('adding two packets with headers', function() {
- var subject = new Writer(10).addCString("!");
- subject.addHeader(0x50);
- subject.addCString("!!");
- subject.addHeader(0x40);
- subject.addCString("!");
- var result = subject.flush(0x10);
- assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0, 0x40, 0, 0, 0, 7, 33, 33, 0, 0x10, 0, 0, 0, 6, 33, 0 ]);
- })
-})
Something went wrong with that request. Please try again.