From b2206ba0b2535d7e5e054c41a6df3925f63f783a Mon Sep 17 00:00:00 2001 From: pyoor Date: Wed, 1 Aug 2018 12:01:42 -0400 Subject: [PATCH 01/13] Revert "Only escape required characters (non-ASCII safe)" This reverts commit be27c5057c0b0e4546b07adac07434f50f3bf3c6. --- lib/utils/common.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utils/common.js b/lib/utils/common.js index 7e1f278..f9b3101 100644 --- a/lib/utils/common.js +++ b/lib/utils/common.js @@ -32,9 +32,9 @@ class common extends utils { static quote (s) { if (typeof s === 'string') { - return `'${jsesc(s, {minimal: true})}'` + return `'${jsesc(s)}'` } else { - return jsesc(s, {minimal: true}) + return jsesc(s) } } From 21a6025481a3cda143c922a672847bf0afb42d54 Mon Sep 17 00:00:00 2001 From: pyoor Date: Thu, 2 Aug 2018 11:26:21 -0400 Subject: [PATCH 02/13] Refactor text generator --- lib/make/text.js | 389 +++++++++++++++++++++++++++++------------------ 1 file changed, 240 insertions(+), 149 deletions(-) diff --git a/lib/make/text.js b/lib/make/text.js index 2d4bbcc..bcdaf25 100644 --- a/lib/make/text.js +++ b/lib/make/text.js @@ -7,18 +7,66 @@ const make = require('../make') const utils = require('../utils') class text extends make { - static lineEnd () { + /** + * Generate a random alphabetic character + */ + static alpha () { + return String.fromCharCode(random.range('A'.charCodeAt(0), 'z'.charCodeAt(0))) + } + + /** + * Generate a random alphanumeric character + */ + static alphanum () { + return String.fromCharCode(random.range('0'.charCodeAt(0), 'z'.charCodeAt(0))) + } + + /** + * Generate a random assignment operator + */ + static assignmentOperator () { return random.pick([ - '\n', '\r', '\r\n', '\n\r' + '=', '+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '&=', '^=', '|=' ]) } + /** + * Generate a random arithmetic operator + */ + static arithmeticOperator () { + return random.pick([ + '%', '-', '+', '*', '/' + ]) + } + + /** + * Generate a random control character + */ static controlChar () { return random.pick([ '\b', '\t', '\n', '\v', '\f', '\r', '\0', '\c', '\a', '\e' // eslint-disable-line no-useless-escape ]) } + /** + * Generate a random digit + */ + static digit () { + return String.fromCharCode(random.range('0'.charCodeAt(0), '9'.charCodeAt(0))) + } + + /** + * Generate a random line ending + */ + static lineEnd () { + return random.pick([ + '\n', '\r', '\r\n', '\n\r' + ]) + } + + /** + * Generate a random token + */ static token () { return random.pick([ '*', '+', '%', '-', '!', '^', ':', '|', '&', '<', '>', '.', '"', @@ -35,9 +83,9 @@ class text extends make { static language () { return random.pick([ // special casing for i, I, dotted/dotless variants - ['tr', 'az'], + ['tr', 'az', 'crh', 'tt', 'ba'], // special casing rules: https://developer.mozilla.org/en/CSS/text-transform - ['nl', 'gr'], + ['nl', 'el', 'ga'], // special justification rules ['ja', 'zh'], // tend to be RTL @@ -49,155 +97,176 @@ class text extends make { ]) } + /** + * Generate a random character that may affect layout + */ static layoutCharCodes () { - return random.pick([ - 0, // null - 160, // non-breaking space - 0x005C, // backslash, but in some countries, represents local currency symbol (e.g. yen) - 0x00AD, // soft hyphen - 0x0BCC, // a Tamil character that is displayed as three glyphs - // http://unicode.org/charts/PDF/U2000.pdf - 0x200B, // zero-width space - 0x200C, // zero-width non-joiner - 0x200D, // zero-width joiner - 0x200E, // left-to-right mark - 0x200F, // right-to-left mark - 0x2011, // non-breaking hyphen - 0x2027, // hyphenation point - 0x2028, // line separator - 0x2029, // paragraph separator - 0x202A, // left-to-right embedding - 0x202B, // right-to-left embedding - 0x202C, // pop directional formatting - 0x202D, // left-to-right override - 0x202E, // right-to-left override - 0x202F, // narrow no-break space - 0x2060, // word joiner - 0x2061, // function application (one of several invisible mathematical operators) - // http://unicode.org/charts/PDF/U3000.pdf - 0x3000, // ideographic space (CJK) - // http://unicode.org/charts/PDF/U0300.pdf - 0x0301, // combining acute accent (if it appears after "a", it turns into "a" with an accent) - // Arabic has the interesting property that most letters connect to the next letter. - // Some code calls this "shaping". - 0x0643, // arabic letter kaf - 0x0645, // arabic letter meem - 0x06CD, // arabic letter yeh with tail - 0xFDDE, // invalid unicode? but somehow associated with arabic. - // http://unicode.org/reports/tr36/tr36-7.html#Buffer_Overflows - // Characters with especially high expansion factors when they go through various unicode "normalizations" - 0x1F82, - 0xFDFA, - 0xFB2C, - 0x0390, - // 0x1D160, // hmm, need surrogates - // Characters with especially high expansion factors when lowercased or uppercased - 0x023A, - 0x0041, - 0xDC1D, // a low surrogate - 0xDB00, // a high surrogate - // UFFF0.pdf - 0xFFF9, // interlinear annotation anchor - 0xFFFA, // interlinear annotation seperator - 0xFFFB, // interlinear annotation terminator - 0xFFFC, // object replacement character - 0xFFFD, // replacement character - 0xFEFF, // zero width no-break space - 0xFFFF, // not a character - 0x00A0, // no-break space - 0x2426, - 0x003F, - 0x00BF, - 0xDC80, - 0xDCFF, - // http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters - 0x205F, // mathematical space - 0x2061, // mathematical function application - 0x2064, // mathematical invisible separator - 0x2044 // fraction slash character - ]) + return String.fromCodePoint( + random.pick([ + 0, // null + 160, // non-breaking space + 0x005C, // backslash, but in some countries, represents local currency symbol (e.g. yen) + 0x00AD, // soft hyphen + 0x0BCC, // a Tamil character that is displayed as three glyphs + // http://unicode.org/charts/PDF/U2000.pdf + 0x200B, // zero-width space + 0x200C, // zero-width non-joiner + 0x200D, // zero-width joiner + 0x200E, // left-to-right mark + 0x200F, // right-to-left mark + 0x2011, // non-breaking hyphen + 0x2027, // hyphenation point + 0x2028, // line separator + 0x2029, // paragraph separator + 0x202A, // left-to-right embedding + 0x202B, // right-to-left embedding + 0x202C, // pop directional formatting + 0x202D, // left-to-right override + 0x202E, // right-to-left override + 0x202F, // narrow no-break space + 0x2060, // word joiner + 0x2061, // function application (one of several invisible mathematical operators) + // http://unicode.org/charts/PDF/U3000.pdf + 0x3000, // ideographic space (CJK) + // http://unicode.org/charts/PDF/U0300.pdf + 0x0301, // combining acute accent (if it appears after "a", it turns into "a" with an accent) + // Arabic has the interesting property that most letters connect to the next letter. + // Some code calls this "shaping". + 0x0643, // arabic letter kaf + 0x0645, // arabic letter meem + 0x06CD, // arabic letter yeh with tail + 0xFDDE, // invalid unicode? but somehow associated with arabic. + // http://unicode.org/reports/tr36/tr36-7.html#Buffer_Overflows + // Characters with especially high expansion factors when they go through various unicode "normalizations" + 0x1F82, + 0xFDFA, + 0xFB2C, + 0x0390, + // 0x1D160, // hmm, need surrogates + // Characters with especially high expansion factors when lowercased or uppercased + 0x023A, + 0x0041, + 0xDC1D, // a low surrogate + 0xDB00, // a high surrogate + // UFFF0.pdf + 0xFFF9, // interlinear annotation anchor + 0xFFFA, // interlinear annotation seperator + 0xFFFB, // interlinear annotation terminator + 0xFFFC, // object replacement character + 0xFFFD, // replacement character + 0xFEFF, // zero width no-break space + 0xFFFF, // not a character + 0x00A0, // no-break space + 0x2426, + 0x003F, + 0x00BF, + 0xDC80, + 0xDCFF, + // http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters + 0x205F, // mathematical space + 0x2061, // mathematical function application + 0x2064, // mathematical invisible separator + 0x2044 // fraction slash character + ]) + ) } + /** + * Generate a random character that affects bidi layout + */ static bidiCharCodes () { - return random.pick([ - 0x0660, // START_HINDI_DIGITS - 0x0669, // END_HINDI_DIGITS - 0x066A, // START_ARABIC_SEPARATOR - 0x066B, // END_ARABIC_SEPARATOR - 0x0030, // START_ARABIC_DIGITS - 0x0039, // END_ARABIC_DIGITS - 0x06f0, // START_FARSI_DIGITS - 0x06f9 // END_FARSI_DIGITS - ]) + return String.fromCodePoint( + random.pick([ + 0x0660, // START_HINDI_DIGITS + 0x0669, // END_HINDI_DIGITS + 0x066A, // START_ARABIC_SEPARATOR + 0x066B, // END_ARABIC_SEPARATOR + 0x0030, // START_ARABIC_DIGITS + 0x0039, // END_ARABIC_DIGITS + 0x06f0, // START_FARSI_DIGITS + 0x06f9 // END_FARSI_DIGITS + ]) + ) } - // http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt - static unicodeCombiningCharacters () { - return random.item([ - [0x0300, 0x036F], // Combining Diacritical Marks - [0x0483, 0x0489], - [0x07EB, 0x07F3], - [0x135D, 0x135F], - [0x1A7F, 0x1A7F], - [0x1B6B, 0x1B73], - [0x1DC0, 0x1DFF], // Combining Diacritical Marks Supplement - [0x20D0, 0x2DFF], - [0x3099, 0x309A], - [0xA66F, 0xA6F1], - [0xA8E0, 0xA8F1], - [0xFE20, 0xFE26], // Combining Half Marks - [0x101FD, 0x101FD], - [0x1D165, 0x1D169], - [0x1D16D, 0x1D172], - [0x1D17B, 0x1D18B], - [0x1D1AA, 0x1D1AD], - [0x1D242, 0x1D244] - ]) + /** + * Generate a random unicode combining character + * http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt + */ + static unicodeCombiningCharacter () { + return String.fromCodePoint( + random.range( + ...random.item([ + [0x0300, 0x036F], // Combining Diacritical Marks + [0x0483, 0x0489], + [0x07EB, 0x07F3], + [0x135D, 0x135F], + [0x1A7F, 0x1A7F], + [0x1B6B, 0x1B73], + [0x1DC0, 0x1DFF], // Combining Diacritical Marks Supplement + [0x20D0, 0x2DFF], + [0x3099, 0x309A], + [0xA66F, 0xA6F1], + [0xA8E0, 0xA8F1], + [0xFE20, 0xFE26], // Combining Half Marks + [0x101FD, 0x101FD], + [0x1D165, 0x1D169], + [0x1D16D, 0x1D172], + [0x1D17B, 0x1D18B], + [0x1D1AA, 0x1D1AD], + [0x1D242, 0x1D244] + ]) + ) + ) } + /** + * Generate a random basic multilingual plane character + */ static unicodeBMP () { - return random.item([ - // BMP = Basic Multilingual Plane - [0x0000, 0xFFFF] - ]) + return String.fromCodePoint( + random.range(0x0000, 0xFFFF) + ) } + /** + * Generate a random supplementary multilingual plane character + */ static unicodeSMP () { - return random.item([ - // SMP = Supplementary Multilingual Plane - [0x10000, 0x13FFF], - [0x16000, 0x16FFF], - [0x1B000, 0x1BFFF], - [0x1D000, 0x1DFFF], - [0x1F000, 0x1FFFF] - ]) + return String.fromCodePoint( + random.range( + ...random.item([ + [0x10000, 0x13FFF], + [0x16000, 0x16FFF], + [0x1B000, 0x1BFFF], + [0x1D000, 0x1DFFF], + [0x1F000, 0x1FFFF] + ]) + ) + ) } + /** + * Generate a random supplementary ideographic plane character + */ static unicodeSIP () { - return random.item([ - // SIP = Supplementary Ideographic Plane - [0x20000, 0x2BFFF], - [0x2F000, 0x2FFFF] - ]) + return String.fromCodePoint( + random.range( + ...random.item([ + [0x20000, 0x2BFFF], + [0x2F000, 0x2FFFF] + ]) + ) + ) } + /** + * Generate a random supplementary special-purpose plane character + */ static unicodeSSP () { - return random.item([ - // SSP = Supplementary Special-purpose Plane - [0xE0000, 0xE0FFF] - ]) - } - - static assignmentOperator () { - return random.pick([ - '=', '+=', '-=', '*=', '/=', '%=', '**=', '<<=', '>>=', '>>>=', '&=', '^=', '|=' - ]) - } - - static arithmeticOperator () { - return random.pick([ - '%', '-', '+', '*', '/' - ]) + return String.fromCodePoint( + random.range(0xE0000, 0xE0FFF) + ) } static currency () { @@ -222,26 +291,48 @@ class text extends make { return utils.common.quote(text.any()) } - static chars () { - return random.pick([ - text.controlChar, - text.token, - text.assignmentOperator, - text.arithmeticOperator, - String.fromCharCode(text.layoutCharCodes()), - String.fromCharCode(text.bidiCharCodes()) + /** + * Wrapper for all text generators + * @returns {string} + */ + static random () { + return random.choose([ + [1, text.alpha], + [1, text.alphanum], + [1, text.arithmeticOperator], + [1, text.assignmentOperator], + [1, text.controlChar], + [1, text.digit], + [1, text.lineEnd], + [1, text.token], + [3, text.layoutCharCodes], + [3, text.bidiCharCodes], + [3, text.unicodeCombiningCharacter], + [3, text.unicodeBMP], + [3, text.unicodeSMP], + [3, text.unicodeSIP], + [3, text.unicodeSSP] ]) } + /** + * Generate a single character + */ + static character () { + return text.random().charAt(0) + } + + /** + * Generate string comprised of random generators + */ static any () { - // Generate a string compromised of random individual characters - // This might be too slow to used for all 'texts' uses let s = '' - // TODO: Len calculation take from DOMFuzz - maybe we should revise this? - let len = random.pick([make.number.tiny, make.number.range]) - for (let i = 0; i < len; i++) { - s += make.text.chars() + let len = random.range(1, 126) + + while (len--) { + s += make.text.random() } + return s } } From 195411fe8d5ad91d730df8138b8e407599aa9540 Mon Sep 17 00:00:00 2001 From: pyoor Date: Thu, 2 Aug 2018 14:21:27 -0400 Subject: [PATCH 03/13] Major rework of make.number --- lib/make/numbers.js | 91 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/lib/make/numbers.js b/lib/make/numbers.js index d96b7f2..86a40f5 100644 --- a/lib/make/numbers.js +++ b/lib/make/numbers.js @@ -6,8 +6,94 @@ const make = require('../make') const random = require('../random') class number extends make { - static bool () { - return random.bool() + /** + * generate a number that exceeds the supplied boundary by +- 3 + * @param start + * @param end + * @private + */ + static _exceed (start, end) { + const value = random.item([start, end]) + const offset = random.range(-3, 3) + return value + offset + } + + /** + * Generate a int8 [-128, 127] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {number} + */ + static int8 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(-128, 127) + } + + return random.range(-128, 127) + } + + /** + * Generate a uint8 [0, 255] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {number} + */ + static uint8 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(0, 255) + } + + return random.range(0, 255) + } + + /** + * Generate a int16 [-32768, 32767] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {number} + */ + static int16 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(-32768, 32767) + } + + return random.range(-32768, 32767) + } + + /** + * Generate a uint16 [0, 65535] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {*} + */ + static uint16 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(0, 65535) + } + + return random.range(-0, 65535) + } + + /** + * Generate a int32 [-2147483648, 2147483647] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {number} + */ + static int32 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(-2147483648, 2147483647) + } + + return random.range(-2147483648, 2147483647) + } + + /** + * Generate a uint32 [0, 4294967295] + * @param bypass {boolean} - Determines if the range should be exceeded + * @returns {number} + */ + static uint32 (bypass = false) { + if (bypass || random.chance(50)) { + return number._exceed(0, 4294967295) + } + + return random.range(0, 4294967295) } static float () { @@ -74,6 +160,7 @@ class number extends make { static any () { let value = random.choose([ + [1, number.interesting], [1, number.float], [1, number.unsigned], [1, [number.range, number.tiny]] From 80f16a4aaf26efe3b54ad731c4b0eafa6b1e8a9e Mon Sep 17 00:00:00 2001 From: pyoor Date: Thu, 2 Aug 2018 14:26:17 -0400 Subject: [PATCH 04/13] Only escape minimal characters and allow HTML escapes --- lib/utils/common.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/utils/common.js b/lib/utils/common.js index f9b3101..d30f0ed 100644 --- a/lib/utils/common.js +++ b/lib/utils/common.js @@ -30,11 +30,22 @@ class common extends utils { return list } - static quote (s) { + /** + * Escape and quote a string + * @param s {string} - String to be quoted + * @param html {boolean} - Identifies whether the string must be HTML safe + * @returns {*} + */ + static quote (s, html = false) { + const options = { + minimal: true, + isScriptContext: html + } + if (typeof s === 'string') { - return `'${jsesc(s)}'` + return `'${jsesc(s, options)}'` } else { - return jsesc(s) + return jsesc(s, options) } } From b47a281403db961fc928d1fb22abe2f8b4a3516f Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 6 Aug 2018 10:22:21 -0400 Subject: [PATCH 05/13] Add additional strategies to make._exceed --- lib/make/numbers.js | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/make/numbers.js b/lib/make/numbers.js index 86a40f5..0088850 100644 --- a/lib/make/numbers.js +++ b/lib/make/numbers.js @@ -7,15 +7,23 @@ const random = require('../random') class number extends make { /** - * generate a number that exceeds the supplied boundary by +- 3 - * @param start - * @param end + * Generate a number that is more likely to exceed the supplied boundary + * @param value {number} * @private */ - static _exceed (start, end) { - const value = random.item([start, end]) - const offset = random.range(-3, 3) - return value + offset + static _exceed (value) { + switch (random.number(4)) { + case 0: + // Divisions + return Math.ceil(value / random.range(2, 4)) + case 1: + // Powers + const offset = Math.pow(2, random.range(1, 7)) + return (value > 0) ? (value - offset) : value + offset + default: + // Slightly less than limit + return (value > 0) ? (value - random.number(3)) : value + random.number(3) + } } /** @@ -25,7 +33,10 @@ class number extends make { */ static int8 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(-128, 127) + return number._exceed(random.choose([ + [1, -128], + [10, 127] + ])) } return random.range(-128, 127) @@ -38,7 +49,7 @@ class number extends make { */ static uint8 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(0, 255) + return number._exceed(255) } return random.range(0, 255) @@ -51,7 +62,10 @@ class number extends make { */ static int16 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(-32768, 32767) + return number._exceed(random.choose([ + [1, -32768], + [10, 32767] + ])) } return random.range(-32768, 32767) @@ -64,7 +78,7 @@ class number extends make { */ static uint16 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(0, 65535) + return number._exceed(65535) } return random.range(-0, 65535) @@ -77,7 +91,10 @@ class number extends make { */ static int32 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(-2147483648, 2147483647) + return number._exceed(random.choose([ + [1, -2147483648], + [10, 2147483647] + ])) } return random.range(-2147483648, 2147483647) @@ -90,7 +107,7 @@ class number extends make { */ static uint32 (bypass = false) { if (bypass || random.chance(50)) { - return number._exceed(0, 4294967295) + return number._exceed(4294967295) } return random.range(0, 4294967295) From e95c56bb7fa3fa099ac6bbc4666c93ab85a86bdd Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 13 Aug 2018 09:35:47 -0400 Subject: [PATCH 06/13] Significantly reduce the weight of large int numbers --- lib/make/numbers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/make/numbers.js b/lib/make/numbers.js index 0088850..99de227 100644 --- a/lib/make/numbers.js +++ b/lib/make/numbers.js @@ -169,8 +169,8 @@ class number extends make { static interesting () { return random.choose([ - [10, [-128, -1, 0, 1, 16, 32, 64, 100, 127]], - [7, [-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767]], + [50, [-128, -1, 0, 1, 16, 32, 64, 100, 127]], + [30, [-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767]], [1, [-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647]] ]) } From 68c606d0dd3c74f7b3a2b0408b9aa1654cbc3bfe Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 13 Aug 2018 10:59:05 -0400 Subject: [PATCH 07/13] Additional JSDoc fixes --- lib/random/random.js | 2 +- lib/utils/common.js | 51 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/random/random.js b/lib/random/random.js index 3a86f64..ec87107 100644 --- a/lib/random/random.js +++ b/lib/random/random.js @@ -81,7 +81,7 @@ class random { /** * Returns a random index from a list * @param {Array} list - * @returns list[n] + * @returns {*} */ static item (list) { if (!Array.isArray(list)) { diff --git a/lib/utils/common.js b/lib/utils/common.js index d30f0ed..d35f2ef 100644 --- a/lib/utils/common.js +++ b/lib/utils/common.js @@ -5,6 +5,11 @@ const jsesc = require('jsesc') const utils = require('../utils') class common extends utils { + /** + * Return stringified object + * @param obj + * @returns {string} + */ static objToString (obj) { try { return `${obj}` @@ -13,6 +18,11 @@ class common extends utils { } } + /** + * Return enumerable properties recursively + * @param obj + * @returns {Array} + */ static getAllProperties (obj) { let list = [] while (obj) { @@ -22,6 +32,11 @@ class common extends utils { return list } + /** + * Return all properties (non-recursive) + * @param obj + * @returns {Array} + */ static getKeysFromHash (obj) { let list = [] for (let p in obj) { @@ -32,8 +47,8 @@ class common extends utils { /** * Escape and quote a string - * @param s {string} - String to be quoted - * @param html {boolean} - Identifies whether the string must be HTML safe + * @param s - String to be quoted + * @param {boolean} html - Identifies whether the string must be HTML safe * @returns {*} */ static quote (s, html = false) { @@ -49,9 +64,13 @@ class common extends utils { } } + /** + * Unicode safe b64 encoding + * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem + * @param {string} str + * @returns {*} + */ static b64encode (str) { - // Unicode safe b64 encoding - // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem if (process.browser) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function toSolidBytes (match, p1) { @@ -64,9 +83,13 @@ class common extends utils { } } + /** + * Unicode safe b64 decoding + * https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem + * @param {string} str + * @returns {*} + */ static b64decode (str) { - // Unicode safe b64 decoding - // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_Unicode_Problem if (process.browser) { return decodeURIComponent(atob(str).split('').map(function (c) { return `%${('00' + c.charCodeAt(0).toString(16)).slice(-2)}` @@ -76,6 +99,11 @@ class common extends utils { } } + /** + * Remove duplicate items from a list + * @param {Array} list + * @returns {Array} + */ static uniqueList (list) { let tmp = {} let r = [] @@ -88,6 +116,12 @@ class common extends utils { return r } + /** + * Merge two objects recursively + * @param {Object} obj1 + * @param {Object} obj2 + * @returns {*} + */ static mergeHash (obj1, obj2) { for (let p in obj2) { try { @@ -103,6 +137,11 @@ class common extends utils { return obj1 } + /** + * Template string beautifier + * @param {Object} obj + * @returns {string} + */ static mockup (obj) { return obj.split('\n').map((ln) => ln.trim()).join('') } From 946e3224064a57e51aa5edc61383208c19082463 Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:20:36 -0400 Subject: [PATCH 08/13] Refactor make.arrays.filledArray --- lib/make/arrays.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/make/arrays.js b/lib/make/arrays.js index 639461e..0d05fb6 100644 --- a/lib/make/arrays.js +++ b/lib/make/arrays.js @@ -6,13 +6,18 @@ const make = require('../make') const random = require('../random') class arrays extends make { - static filledArray (fn, limit) { - let array = [] - let size = limit || random.number(make.number.tiny()) + 1 + /** + * Returns an array containing random values generated by the supplied function + * @param {Function} fn - Function used to generate values + * @param {number} limit - Length of the array + * @returns {Array} + */ + static filledArray (fn, limit = make.number.tiny()) { + const array = [] - for (let i = 0; i < size; i++) { - let value = random.pick(fn) - if (value !== undefined) { + for (let i = 0; i < limit; i++) { + const value = random.pick(fn) + if (value !== null) { array.push(value) } } From 0683dc88fb6aa3ab86196e5b278113b43ccdcf92 Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:21:12 -0400 Subject: [PATCH 09/13] Use make.number.tiny instead of make.number.range --- lib/make/network.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/make/network.js b/lib/make/network.js index ce4e233..f962479 100644 --- a/lib/make/network.js +++ b/lib/make/network.js @@ -141,7 +141,7 @@ class network extends make { } static dtmf () { - let count = make.number.range() + let count = make.number.tiny() const values = [] while (count--) { values.push(random.item(['*', '#', 'A', 'B', 'C', 'D', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])) From fa47ea0d70b1f3ab68976d51ca2ad56ac4c03222 Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:21:37 -0400 Subject: [PATCH 10/13] Remove non-typed generators from make.typed.any --- lib/make/typed.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/make/typed.js b/lib/make/typed.js index 53bc4e1..2c5b953 100644 --- a/lib/make/typed.js +++ b/lib/make/typed.js @@ -82,8 +82,7 @@ class typed extends make { [1, [typed.short, typed.unsignedShort]], [1, [typed.long, typed.unsignedLong]], [1, [typed.float, typed.unrestrictedFloat]], - [1, [typed.double, typed.unrestrictedDouble]], - [1, [make.number.range, make.number.tiny]] + [1, [typed.double, typed.unrestrictedDouble]] ]) } From ad5ae5656162e5a609b8e3fa8c091c318a542eae Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:21:54 -0400 Subject: [PATCH 11/13] Use make.number.tiny instead of make.number.range --- lib/utils/script.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/script.js b/lib/utils/script.js index 81ef852..e73730f 100644 --- a/lib/utils/script.js +++ b/lib/utils/script.js @@ -43,7 +43,7 @@ class script extends utils { } static makeLoop (s, max) { - return `for (let i = 0; i < ${max || make.number.range()}; i++) {${s}}` + return `for (let i = 0; i < ${max || make.number.tiny()}; i++) {${s}}` } static makeRandomOptions (baseObject) { From e611cb8a1992e78255c9793e1fadc0eb7b9bd7e5 Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:22:16 -0400 Subject: [PATCH 12/13] Further refactoring of make.numbers --- lib/make/numbers.js | 117 ++++++++++++++++++++++++++++---------------- 1 file changed, 74 insertions(+), 43 deletions(-) diff --git a/lib/make/numbers.js b/lib/make/numbers.js index 99de227..cef5d97 100644 --- a/lib/make/numbers.js +++ b/lib/make/numbers.js @@ -7,7 +7,7 @@ const random = require('../random') class number extends make { /** - * Generate a number that is more likely to exceed the supplied boundary + * Returns a number that is more likely to exceed the supplied boundary * @param value {number} * @private */ @@ -27,7 +27,7 @@ class number extends make { } /** - * Generate a int8 [-128, 127] + * Returns a int8 [-128, 127] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {number} */ @@ -43,7 +43,7 @@ class number extends make { } /** - * Generate a uint8 [0, 255] + * Returns a uint8 [0, 255] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {number} */ @@ -56,7 +56,7 @@ class number extends make { } /** - * Generate a int16 [-32768, 32767] + * Returns a int16 [-32768, 32767] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {number} */ @@ -72,7 +72,7 @@ class number extends make { } /** - * Generate a uint16 [0, 65535] + * Returns a uint16 [0, 65535] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {*} */ @@ -85,7 +85,7 @@ class number extends make { } /** - * Generate a int32 [-2147483648, 2147483647] + * Returns a int32 [-2147483648, 2147483647] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {number} */ @@ -101,7 +101,7 @@ class number extends make { } /** - * Generate a uint32 [0, 4294967295] + * Returns a uint32 [0, 4294967295] * @param bypass {boolean} - Determines if the range should be exceeded * @returns {number} */ @@ -113,36 +113,34 @@ class number extends make { return random.range(0, 4294967295) } + /** + * Returns a random floating point number + * @returns {number} + */ static float () { - let n - if (random.chance(32)) { + /* if (random.chance(32)) { switch (random.number(4)) { case 0: - n = random.range(Number.MIN_VALUE, Number.MAX_VALUE) - break + return random.range(Number.MIN_VALUE, Number.MAX_VALUE) case 1: - n = Math.pow(10, 1) / Math.pow(10, random.number(307)) - break + return Math.pow(10, 1) / Math.pow(10, random.number(307)) case 2: - n = Math.pow(2, random.float() * random.float() * 64) - break + return Math.pow(2, random.float() * random.float() * 64) case 3: - n = Math.pow(10, random.range(1, 9)) / Math.pow(10, random.range(1, 9)) - break + return Math.pow(10, random.range(1, 9)) / Math.pow(10, random.range(1, 9)) } - return n - } - switch (random.number(6)) { - default: - n = random.float() - } - return n - } - - static range () { - return random.pick([1, 2, 3, 4, 6, 8, 16, 32, 64, number.tiny]) + } */ + + return random.float() } + /** + * Returnss a float value within the supplied range + * @param {number} min - Start value + * @param {number} max - End value + * @param {number} precision + * @returns {number} + */ static frange (min, max, precision) { let x = Math.random() * (min - max) + max if (precision) { @@ -152,21 +150,28 @@ class number extends make { return x } + /** + * Returnss a random power of 2 between 1 and 2048 + * @returns {number} + */ static tiny () { - return Math.pow(2, random.number(12)) - } - - static unsigned () { - if (random.chance(2)) { - return Math.abs(number.any()) - } - return Math.pow(2, random.number(random.number(65))) + random.number(3) - 1 + // Calling random.number twice prefers lower values + return Math.pow(2, random.number(random.number(13))) } + /** + * Returns a random number adjacent to the supplied number + * @param {number} number + * @returns {number} + */ static even (number) { return number % 2 === 1 ? ++number : number } + /** + * Returns a random number that may be interesting + * @returns {number} + */ static interesting () { return random.choose([ [50, [-128, -1, 0, 1, 16, 32, 64, 100, 127]], @@ -175,14 +180,40 @@ class number extends make { ]) } - static any () { - let value = random.choose([ - [1, number.interesting], - [1, number.float], - [1, number.unsigned], - [1, [number.range, number.tiny]] + /** + * Returns a random signed number + * @returns {number} + */ + static signed () { + return random.choose([ + [50, [number.int8]], + [30, [number.int16]], + [1, [number.int32]] + ]) + } + + /** + * Returns a random unsigned number + * @returns {number} + */ + static unsigned () { + return random.choose([ + [50, [number.uint8]], + [30, [number.uint16]], + [1, [number.uint32]] + ]) + } + + /** + * Returns a random number using the type base number generators above + * @returns {number} + */ + static any () { + return random.choose([ + [50, [number.int8, number.uint8]], + [30, [number.int16, number.uint16]], + [1, [number.int32, number.uint32]] ]) - return random.chance(10) ? -value : value } } From 9ba9cf453b91b7b75a63785063412c538053f784 Mon Sep 17 00:00:00 2001 From: pyoor Date: Mon, 20 Aug 2018 12:54:21 -0400 Subject: [PATCH 13/13] Fix typos in docstring --- lib/make/numbers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/make/numbers.js b/lib/make/numbers.js index cef5d97..8faab16 100644 --- a/lib/make/numbers.js +++ b/lib/make/numbers.js @@ -135,7 +135,7 @@ class number extends make { } /** - * Returnss a float value within the supplied range + * Returns a float value within the supplied range * @param {number} min - Start value * @param {number} max - End value * @param {number} precision @@ -151,7 +151,7 @@ class number extends make { } /** - * Returnss a random power of 2 between 1 and 2048 + * Returns a random power of 2 between 1 and 2048 * @returns {number} */ static tiny () {