Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truncate Typed Arrays (#441) #576

Merged
merged 7 commits into from
Jan 5, 2016
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 50 additions & 2 deletions lib/chai/utils/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var getEnumerableProperties = require('./getEnumerableProperties');
module.exports = inspect;

/**
* Echos the value of a value. Trys to print the value out
* Echos the value of a value. Tries to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
Expand Down Expand Up @@ -120,7 +120,15 @@ function formatValue(ctx, value, recurseTimes) {
}
}

var base = '', array = false, braces = ['{', '}'];
var base = ''
, array = false
, typedArray = false
, braces = ['{', '}'];

if (isTypedArray(value)) {
typedArray = true;
braces = ['[', ']'];
}

// Make Array say that they are Array
if (isArray(value)) {
Expand Down Expand Up @@ -167,6 +175,8 @@ function formatValue(ctx, value, recurseTimes) {
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else if (typedArray) {
output = formatTypedArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
Expand Down Expand Up @@ -221,6 +231,7 @@ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
output.push('');
}
}

keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
Expand All @@ -230,6 +241,28 @@ function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
return output;
}

function formatTypedArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];

// Truncating TypedArray if it has more than 1000 elements
var l = value.length > 1000 ? 5 : value.length;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems strange - if I had an array with 999 elements it would show all 999, but with 1000 it would only show 5?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I thought this was a little bit strange too, but I had no idea how you guys would like the representation of the Array to be, are there any guidelines?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have chai.config.truncateTreshold which could be used as a metric - but I suppose my point was less about the cutoff figure, but more that the cutoff makes a dramatic change. If it was var l = value.length > 1000 ? 1000 : value.length; it would make much more sense (although 1000 is maybe a bit too high still, perhaps a number like 20 or so?)


for (var i = 0; i < l; ++i) {
if (Object.prototype.hasOwnProperty.call(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest I haven't used Typed Arrays at all so don't know the best way to show two in a comparison - is showing the start a good idea? For files expressed as typed arrays the first few bytes are going to be magic bytes right, so will largely always be identical?

} else {
output.push('');
}
}

// If TypedArray has been truncated we add '...' to its end
if (l !== value.length) {
output.push('...');
}

return output;
}

function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str;
Expand Down Expand Up @@ -311,6 +344,21 @@ function reduceToSingleString(output, base, braces) {
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}

function isTypedArray(ar) {
// Unfortunately there's no way to check if an object is a TypedArray
// We have to check if it's one of these types
return (typeof ar === 'object' &&
objectToString(ar) === '[object Int8Array]' ||
objectToString(ar) === '[object Uint8Array]' ||
objectToString(ar) === '[object Uint8ClampedArray]' ||
objectToString(ar) === '[object Int16Array]' ||
objectToString(ar) === '[object Uint16Array]' ||
objectToString(ar) === '[object Int32Array]' ||
objectToString(ar) === '[object Uint32Array]' ||
objectToString(ar) === '[object Float32Array]' ||
objectToString(ar) === '[object Float64Array]');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose it is open to abuse, but you could just use:

/\w+Array]$/.test(objectToString(ar))


function isArray(ar) {
return Array.isArray(ar) ||
(typeof ar === 'object' && objectToString(ar) === '[object Array]');
Expand Down
59 changes: 59 additions & 0 deletions test/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,65 @@ describe('utilities', function () {
});
});

it('inspect every kind of available TypedArray', function () {
chai.use(function (_chai, _) {
var arr = [1, 2, 3]
, exp = '[ 1, 2, 3 ]'
, isNode = true;

if (typeof window !== 'undefined') {
isNode = false;
}

// Checks if engine supports common TypedArrays
if ((!isNode && 'Int8Array' in window) ||
isNode && typeof 'Int8Array' !== undefined) {
// Typed array inspections should work as array inspections do
expect(_.inspect(new Int8Array(arr))).to.equal(exp);
expect(_.inspect(new Uint8Array(arr))).to.equal(exp);
expect(_.inspect(new Int16Array(arr))).to.equal(exp);
expect(_.inspect(new Uint16Array(arr))).to.equal(exp);
expect(_.inspect(new Int32Array(arr))).to.equal(exp);
expect(_.inspect(new Uint32Array(arr))).to.equal(exp);
expect(_.inspect(new Float32Array(arr))).to.equal(exp);
}

// These ones may not be available alongside the others above
if ((!isNode && 'Uint8ClampedArray' in window) ||
isNode && typeof 'Uint8ClampedArray' !== undefined) {
expect(_.inspect(new Uint8ClampedArray(arr))).to.equal(exp);
}

if ((!isNode && 'Float64Array' in window) ||
isNode && typeof 'Float64Array' !== undefined) {
expect(_.inspect(new Float64Array(arr))).to.equal(exp);
}
});
});

it('truncate long TypedArray', function () {
chai.use(function (_chai, _) {

var arr = []
, exp = '[ 1, 2, 3, 4, 5, ... ]'
, isNode = true;

// Filling arr with lots of elements
for (var i = 1; i <= 1001; i++) {
arr.push(i);
}

if (typeof window !== 'undefined') {
isNode = false;
}

if ((!isNode && 'Int8Array' in window) ||
isNode && typeof 'Int8Array' !== undefined) {
expect(_.inspect(new Int8Array(arr))).to.equal(exp);
}
});
});

it('addChainableMethod', function () {
chai.use(function (_chai, _) {
_chai.Assertion.addChainableMethod('x',
Expand Down