From e05079f4a8102cfa1f06d14203f9dfbbaab8f66e Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 24 Feb 2015 16:24:58 +0100 Subject: [PATCH] feat(rtts_assert): avoid deep recursion in prettyPrint --- modules/rtts_assert/src/rtts_assert.es6 | 21 ++++++++++++--- modules/rtts_assert/test/rtts_assert_spec.es6 | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/modules/rtts_assert/src/rtts_assert.es6 b/modules/rtts_assert/src/rtts_assert.es6 index 3d4c25f070..6c4e3991b5 100644 --- a/modules/rtts_assert/src/rtts_assert.es6 +++ b/modules/rtts_assert/src/rtts_assert.es6 @@ -74,7 +74,15 @@ function assertArgumentTypes(...params) { } } -function prettyPrint(value) { +function prettyPrint(value, depth) { + if (typeof(depth) === 'undefined') { + depth = 0; + } + + if (depth++ > 3) { + return '[...]'; + } + if (typeof value === 'undefined') { return 'undefined'; } @@ -96,12 +104,17 @@ function prettyPrint(value) { return value.__assertName; } - if (value.map) { - return '[' + value.map(prettyPrint).join(', ') + ']'; + if (value.map && typeof value.map === 'function') { + return '[' + value.map((v) => prettyPrint(v, depth)).join(', ') + ']'; } var properties = Object.keys(value); - return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p])).join(', ') + '}'; + var suffix = '}'; + if (properties.length > 20) { + properties.length = 20; + suffix = ', ... }'; + } + return '{' + properties.map((p) => p + ': ' + prettyPrint(value[p], depth)).join(', ') + suffix; } return value.__assertName || value.name || value.toString(); diff --git a/modules/rtts_assert/test/rtts_assert_spec.es6 b/modules/rtts_assert/test/rtts_assert_spec.es6 index 193e359031..e76a264cea 100644 --- a/modules/rtts_assert/test/rtts_assert_spec.es6 +++ b/modules/rtts_assert/test/rtts_assert_spec.es6 @@ -14,6 +14,33 @@ export function main() { +describe('prettyPrint', () => { + class Type {}; + + it('should limit the number of printed properties', () => { + var o = {}; + for (var i = 0; i < 100; i++) { + o['p_' + i] = i; + } + try { + assert.type(o, Type); + throw 'fail!'; + } catch (e) { + expect(e.message.indexOf('p_0')).toBeGreaterThan(-1); + expect(e.message.indexOf('...')).toBeGreaterThan(-1); + expect(e.message.indexOf('p_20')).toBe(-1); + } + }); + + it('should limit the depth of printed properties', () => { + var o = {l1: {l2: {l3: {l4: {l5: {l6: 'deep'}}}}}}; + + expect(() => { + assert.type(o, Type); + }).toThrowError('Expected an instance of Type, got {l1: {l2: {l3: {l4: [...]}}}}!'); + }); +}); + // ## Basic Type Check // By default, `instanceof` is used to check the type. //