Skip to content

Instantly share code, notes, and snippets.

@kriskowal
Created February 22, 2010 01:58
Show Gist options
  • Save kriskowal/310702 to your computer and use it in GitHub Desktop.
Save kriskowal/310702 to your computer and use it in GitHub Desktop.
var ASSERT = require("assert");
var BINARY, Buffer, section, subsection;
exports['test The "binary" module exists'] = function () {
BINARY = require("binary");
};
section = exports['test Constructors'] = {};
section['test A buffer function must exist.'] = function () {
Buffer = BINARY.Buffer;
ASSERT.ok(typeof Buffer === "function");
};
section['test Calling and constructing a Buffer both return a new Buffer ' +
'instance'] = function () {
ASSERT.ok(new Buffer(0) instanceof Buffer);
ASSERT.ok(Buffer(0) instanceof Buffer);
};
section['test Buffers are instances of Buffer and Object'] = function () {
ASSERT.ok(new Buffer(0) instanceof Buffer);
ASSERT.ok(new Buffer(0) instanceof Object);
ASSERT.ok(Buffer(0) instanceof Buffer);
ASSERT.ok(Buffer(0) instanceof Object);
};
section['test The type of a Buffer is "object".'] = function () {
ASSERT.ok(typeof new Buffer(0) === "object");
ASSERT.ok(typeof Buffer(0) === "object");
};
section['test Any call or construction of Buffer that does not have a ' +
'Number, Buffer, Array, or String as its first argument throws a ' +
'TypeError.'] = function () {
ASSERT['throws'](function () {
new Buffer({});
}, TypeError);
ASSERT['throws'](function () {
new Buffer(new Date());
}, TypeError);
// Why does this case throw? Does it make sense to distinguish between boxed
// and unboxed?
// -- ashb Ash Berlin
// To relieve implementors of the burden of having to support unboxing.
// Unboxing would normally be supported for coerced arguments, but it is not
// possible in this case to simply coerce the first argument because the first
// argument must be used to decide which constructor behavior to use.
// -- kriskowal Kris Kowal
ASSERT['throws'](function () {
new Buffer(new Number(0));
}, TypeError);
};
// I'm not sure this is 1) needed, and 2) actually possible to set the
// fn.length from a C++ bound constructor in spidermonkey. Will need to check
// if people think its worth keeping.
// -- ashb Ash Berlin
// I've provisionally removed these requirements; I wouldn't want otherwise
// compliant implementations to be unable to claim that they conform because of
// this requirement.
// -- kriskowal Kris Kowal
/*
section['test The "length" of Buffer is 1'] = function () {
ASSERT.equal(Buffer.length, 1);
};
*/
subsection = section['test Buffer(length Number, Number(fill_opt))'] = {};
subsection['test New Buffer of the given length, with the given fill ' +
'number at all offsets.'] = function () {
[0, 127, 128, 255].forEach(function (fill) {
[0, 7, 8].forEach(function (length) {
var buffer = new Buffer(length, fill);
ASSERT.equal(buffer.length, length);
for (var i = 0, ii = length; i < ii; i++) {
ASSERT.equal(buffer[i], fill);
};
});
});
ASSERT['throws'](function () {
var buffer = new Buffer(0);
buffer[0];
}, RangeError);
ASSERT['throws'](function () {
var buffer = new Buffer(1);
buffer[-1];
}, RangeError);
};
subsection['test The default filler is 0'] = function () {
ASSERT.equal(Buffer(1)[0], 0);
};
subsection = section['test Buffer(source Buffer, Number(start_opt), ' +
'Number(stop_opt), Boolean(copy_opt))'] = {};
subsection['test New Buffer that is either a copy or a view of the ' +
'allocation as the given buffer, from "start" to "stop".'] = function () {
var buffer = Buffer(2);
// [0, 0]
buffer[1] = 1;
// [0, 1]
var copy = Buffer(buffer);
// [0, 1], [0, 1]
ASSERT.equal(copy.length, 2);
ASSERT.equal(copy[0], 0);
ASSERT.equal(copy[1], 1);
copy[1] = 2;
// [0, 1], [0, 2]
ASSERT.equal(buffer[1], 0);
ASSERT.equal(copy[1], 2);
var view = Buffer(buffer, undefined, undefined, false);
// [0, 1]
ASSERT.equal(view.length, 2);
ASSERT.equal(view[0], 0);
ASSERT.equal(view[1], 1);
view[1] = 3;
// [0, 3]
ASSERT.equal(buffer[1], 3);
ASSERT.equal(view[1], 3);
buffer[1] = 4;
// [0, 4]
ASSERT.equal(buffer[1], 4);
ASSERT.equal(view[1], 4);
var range = Buffer(buffer, 1, undefined, false);
// [4]
ASSERT.equal(buffer[1], 4);
ASSERT.equal(range[0], 4);
buffer[1] = 5;
// [4]
ASSERT.equal(range[0], 5);
range[0] = 6;
ASSERT.equal(buffer[1], 6);
var nullBuffer = Buffer(buffer, 1, 1, false);
ASSERT.equal(nullBuffer.length, 0);
};
subsection['test "start" is 0 if undefined or omitted.'] = function () {
var buffer, view;
buffer = Buffer(2);
buffer[0] = 1;
view = Buffer(buffer);
ASSERT.equal(view[0], 1);
view = Buffer(buffer, 1);
ASSERT.equal(view[0], 0);
ASSERT.equal(view.length, 1);
};
subsection['test "stop" is the other buffer\'s length if undefined or ' +
'omitted.'] = function () {
var view, buffer;
buffer = Buffer(2);
view = Buffer(buffer);
ASSERT.equal(view.length, 2);
view = Buffer(buffer, undefined, undefined);
ASSERT.equal(view.length, 2);
};
subsection['test "start" and "stop" may both be negative numbers, in ' +
'which case they correspond to offsets counting from the length of ' +
'the buffer.'] = function () {
var buffer = Buffer([0, 1, 2, 3]);
var slice = new Buffer(buffer, -3, -1);
ASSERT.equal(slice.length, 2);
ASSERT.equal(slice[0], 1);
ASSERT.equal(slice[1], 2);
};
subsection['test "copy" is true if undefined or omitted'] = function () {
var buffer = Buffer([0, 1, 2, 3]);
var slice = new Buffer(buffer);
buffer[0] = 10;
ASSERT.equal(slice[0], 0);
};
subsection['test When true, "copy" indicates that the buffer must have its ' +
'own copy of the allocation.'] = function () {
var buffer = Buffer([0, 1, 2, 3]);
var slice = new Buffer(buffer, undefined, undefined, true);
buffer[0] = 10;
ASSERT.equal(slice[0], 0);
};
subsection['test When false, "copy" indicates that the buffer must share ' +
'its allocation with the given buffer.'] = function () {
var buffer = Buffer([0, 1, 2, 3]);
var slice = new Buffer(buffer, undefined, undefined, false);
buffer[0] = 10;
ASSERT.equal(slice[0], 10);
};
subsection = section['test Buffer(source Array, Number(start_opt), ' +
'Number(stop_opt))'] = {};
subsection['test New Buffer that contains the respective values from the ' +
'given array, from "start" to "stop".'] = function () {
var buffer = new Buffer([0, 1, 2, 3], 1, 3);
ASSERT.equal(buffer.length, 2);
ASSERT.equal(buffer[0], 1);
ASSERT.equal(buffer[1], 2);
};
// as mentioned in the general requirements:
subsection['test Array values are coerced to Number (boxed ' +
'Number)'] = function () {
var buffer = new Buffer([new Number(1)]);
ASSERT.equal(buffer[0], 1);
};
// as mentioned in the general requirements:
subsection['test Array values are coerced to Number ' +
'(valueOf)'] = function () {
var buffer = new Buffer([{
"valueOf": function () {
return 1;
}
}]);
ASSERT.equal(buffer[0], 1);
};
// as mentioned in the general requirements:
subsection['test Array values are masked with 0xFF'] = function () {
var buffer = new Buffer([257]);
ASSERT.equal(buffer[0], 1);
};
subsection['test Array values are coerced to Number and masked with ' +
'0xFF'] = function () {
var buffer = new Buffer([{
"valueOf": function () {
return 257;
}
}]);
ASSERT.equal(buffer[0], 1);
};
subsection['test "stop" is the array\'s "length" if undefined or ' +
'omitted.'] = function () {
var buffer = new Buffer([0, 1, 2, 3]);
ASSERT.equal(buffer.length, 4);
buffer = new Buffer([0, 1, 2, 3], 1, undefined);
ASSERT.equal(buffer.length, 3);
};
/*
subsection['test The "length" of the new buffer is exactly the length from ' +
'"start" to "stop".'] = function () {
// TODO
};
*/
subsection['test "start" and "stop" may both be negative numbers, in which ' +
'case they correspond to offsets counting from the length of the ' +
'array.'] = function () {
// TODO
};
subsection = section['test Buffer(string String, String(charset))'] = {};
subsection['test Create a buffer from a string, the result being encoded ' +
'with "charset".'] = function () {
// TODO
};
// implied
section['test Constructing a Buffer with a String and no charset throws ' +
'a TypeError'] = function () {
ASSERT['throws'](function () {
new Buffer('');
}, TypeError);
};
section = exports['test Prototype Properties'] = {};
subsection = exports['test toString() String'] = {};
subsection['test Returns a debug representation like "[Buffer 10]", ' +
'where 10 is the length this Buffer.'] = function () {
// TODO
};
subsection['test This behavior of "toString" occurs if the ' +
'"arguments.length" is 0.'] = function () {
// TODO
};
subsection = section['test toString(String(charset)) String'] = {};
subsection['test Decodes this according to the given character set and ' +
'returns the String from the corresponding unicode points.'] = function () {
// TODO
};
subsection['test Throws a ValueError if the buffer is malformed for the ' +
'given character set or if any of the code points are out of the ' +
'implementation\'s supported range.'] = function () {
// TODO
};
subsection['test This behavior of "toString" occurs if the ' +
'"arguments.length" is not 0.'] = function () {
// TODO
};
/*
section['test The "length" of "toString" is 1.'] = function () {
// TODO
};
*/
subsection = section['test toSource() String'] = {};
subsection['test Returns "<tt>require("binary").Buffer([])</tt>" for a ' +
'null buffer or "<tt>require("binary").Buffer([0, 1, 2])</tt>" for a ' +
'buffer of length 3 with bytes 0, 1, and 2.'] = function () {
// TODO
};
/*
subsection['test The "length" of "toSource" is 0.'] = function () {
// TODO
};
*/
subsection = section['test range(Number(start_opt), Number(stop_opt)) ' +
'Buffer'] = {};
subsection['test Returns a Buffer that views the given range of the ' +
'same allocated byte buffer.'] = function () {
// TODO
};
subsection['test "start" is 0 if undefined or omitted.'] = function () {
// TODO
};
subsection['test "stop" is the length of this buffer if undefined or ' +
'omitted.'] = function () {
// TODO
};
subsection['"start" and "stop" may be negative numbers, in which case ' +
'they correspond to an offset counting from this buffer\'s ' +
'length.'] = function () {
// TODO
};
subsection['The length of "range" is 2.'] = function () {
// TODO
};
subsection = section['test slice(Number(start_opt), Number(stop_opt)) ' +
'Buffer'] = {};
subsection['test Returns a Buffer with a new internal allocation, ' +
'containing a copy of this buffer from "start" to "stop" ' +
'offsets.'] = function () {
// TODO
};
subsection['test "start" is 0 if undefined or omitted.'] = function () {
// TODO
};
subsection['test "stop" is this buffer\'s length if undefined or ' +
'omitted.'] = function () {
// TODO
};
subsection['test "start" and "stop" may be negative numbers, in which ' +
'case they correspond to an offset counting from this buffer\'s ' +
'length.'] = function () {
// TODO
};
/*
# The "length" of "slice" is 2.
*/
subsection = section['test copy(target, Number(targetStart_opt), ' +
'Number(start_opt)), Number(stop_opt)) Buffer'] = function () {
// TODO
};
subsection['test Copies the Number values of each byte from this ' +
'between "start" and "stop" to a "target" Buffer or Array at the ' +
'"targetStart" offset.'] = function () {
// TODO
};
subsection['test "stop" is the length of this if undefined or ' +
'omitted.'] = function () {
// TODO
};
subsection['test "targetStart", "start", and "stop" are internally ' +
'coerced to Numbers with the Number constructor.'] = function () {
// TODO
};
subsection['test "targetStart" may be negative, in which case it ' +
'corresponds to an offset counting from the length of the ' +
'target.'] = function () {
// TODO
};
subsection['test "start" and "stop" may be negative, in which case they ' +
'correspond to an offset counting from this buffer\'s ' +
'length.'] = function () {
// TODO
};
subsection['test Throws a TypeError if the target is not a Buffer or ' +
'Array.'] = function () {
// TODO
};
subsection['test Returns this.'] = function () {
// TODO
};
/*
# The "length" of "copy" is 1.
*/
subsection = section['test copyFrom(source, Number(sourceStart_opt), ' +
'Number(start_opt), Number(stop_opt)) Buffer'] = {};
subsection['test Copies the Number values of each byte from a given ' +
'Buffer or Array into this from "start" to "stop" from the given ' +
'"sourceStart" offset.'] = function () {
// TODO
};
subsection['test "start" is 0 if undefined or omitted.'] = function () {
// TODO
};
subsection['test "stop" is the length of this buffer if undefined or ' +
'omitted.'] = function () {
// TODO
};
subsection['test "sourceStart" may be negative, in which case it ' +
'corresponds to an offset counting from this buffer\'s ' +
'length.'] = function () {
// TODO
};
subsection['test "start" and "stop" may be negative, in which case they ' +
'correspond to offsets counting from the length of the ' +
'source.'] = function () {
// TODO
};
subsection['test "sourceStart", "start", and "stop" are internally ' +
'coerced to Numbers with the Number constructor.'] = function () {
// TODO
};
subsection['test If the source is an Array, all values of that array are ' +
'coerced to Numbers and masked with 0xFF.'] = function () {
// TODO
};
subsection['test Throws a TypeError if the target is not a Buffer or ' +
'Array.'] = function () {
// TODO
};
subsection['test Returns this.'] = function () {
// TODO
};
/*
# The "length" of "copyFrom" is 1.
*/
subsection = section['test fill(Number(value), Number(start_opt), ' +
'Number(stop_opt)) Buffer'] = {};
subsection['test Fills all of this buffer\'s bytes with the given value ' +
'as a Number from the "start" offset to the "stop" offset.'] = function () {
// TODO
};
subsection['test "start" is 0 if undefined or omitted.'] = function () {
// TODO
};
subsection['test "stop" is the length of this buffer if undefined or ' +
'omitted.'] = function () {
// TODO
};
subsection['test "start" and "stop" may be negative, in which case they ' +
'correspond to offsets counting from the length of this ' +
'buffer.'] = function () {
// TODO
};
subsection['test "value" is 0 if undefined or omitted.'] = function () {
// TODO
};
subsection['test "value" is coerced to Number and masked with ' +
'0xFF.'] = function () {
// TODO
};
subsection['test Returns this.'] = function () {
// TODO
};
/*
# The "length" of "fill" is 1.
*/
subsection = section['test Content'] = {};
subsection['test an alias of Number, indicating that Number is the type ' +
'of what [[Get]] returns.'] = function () {
// TODO
};
section = exports['test Internal Properties'] = {};
subsection = section['test [[Get]] Number'] = {};
subsection['test Returns the Number value of a the byte at the given ' +
'offset.'] = function () {
// TODO
};
subsection = section['test [[Put]] Number'] = {};
subsection['test Sets the byte value at the given offset.'] = function () {
// TODO
};
subsection['test Throws a RangeError if the index is beyond the current ' +
'bounds of the buffer.'] = function () {
// TODO
};
subsection['test Implicitly coerces the value to a Number and masks it ' +
'with 0xFF.'] = function () {
// TODO
};
section = exports['test Instance Properties'] = {};
subsection = section['test length'] = {};
subsection['test The length in bytes.'] = function () {
// TODO
};
subsection['test Not [[Configurable]]'] = function () {
// TODO
};
subsection['test Not [[Enumerable]]'] = function () {
// TODO
};
subsection['test [[ReadOnly]]'] = function () {
// TODO
};
/*
== Notation ==
# The notation functionName(argument Type) indicates that the given behavior
only occurs when the argument pattern matches the given "Type".
# If the functionName(argument Type) is mentioned for an argument and none of
the given forms match the types of the argument, the function must throw a
TypeError.
# The notation functionName(argument_opt) indicates that the argument may be
undefined or omitted.
# The distinction between an omitted or undefined argument is only detectable
by checking the <code>arguments.length</code>
# The notation function(Type(argument)) implies that any type matches the
argument and that it must be internally coerced to the "Type".
# Extra arguments are ignored.
== General Requirements ==
# All of the properties specified on prototypes are not [[Enumerable]] on
instances.
# All operations that copy values to a byte in the byte buffer implicitly
coerce the value to a Number and bit mask such values with 0xFF.
# All operations that require encoding, decoding, or transcoding among charsets
must throw a ValueError if a requested charset is not supported by the
implementation. All implementations must support "ascii", "utf-8", and
"utf-16".
# Charset strings are as defined by IANA
http://www.iana.org/assignments/character-sets.
# Charsets are case insensitive.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment