From 1f1fccc45df9fdc8a77d2ee3f1ae36f029b31ee9 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 3 Apr 2017 04:00:33 +0800 Subject: [PATCH] extend `test/ufuzz.js` (#1769) New expressions: - property access - array literal - object literal Miscellaneous: - reduce execution timeout - test `toplevel` and `mangleProperties` --- test/sandbox.js | 2 +- test/ufuzz.js | 103 +++++++++++++++++++++++++++++++++++++++++------- test/ufuzz.json | 32 +++++++++++++++ 3 files changed, 121 insertions(+), 16 deletions(-) diff --git a/test/sandbox.js b/test/sandbox.js index 504e5e25..396a6e2c 100644 --- a/test/sandbox.js +++ b/test/sandbox.js @@ -29,7 +29,7 @@ exports.run_code = function(code) { })); } } - }, { timeout: 30000 }); + }, { timeout: 5000 }); return stdout; } catch (ex) { return ex; diff --git a/test/ufuzz.js b/test/ufuzz.js index 7aab6715..1bb3f695 100644 --- a/test/ufuzz.js +++ b/test/ufuzz.js @@ -135,6 +135,7 @@ for (var i = 2; i < process.argv.length; ++i) { } var VALUES = [ + '""', 'true', 'false', ' /[a2][^e]+$/ ', @@ -474,25 +475,31 @@ function createExpression(recurmax, noComma, stmtDepth, canThrow) { return _createExpression(recurmax, noComma, stmtDepth, canThrow); } function _createExpression(recurmax, noComma, stmtDepth, canThrow) { - switch (rng(15)) { + switch (rng(31)) { case 0: - return createUnaryOp() + (rng(2) === 1 ? 'a' : 'b'); case 1: - return 'a' + (rng(2) == 1 ? '++' : '--'); + return createUnaryOp() + (rng(2) === 1 ? 'a' : 'b'); case 2: + case 3: + return 'a' + (rng(2) == 1 ? '++' : '--'); + case 4: + case 5: // parens needed because assignments aren't valid unless they're the left-most op(s) in an expression return '(b ' + createAssignment() + ' a)'; - case 3: + case 6: + case 7: return rng(2) + ' === 1 ? a : b'; - case 4: + case 8: + case 9: return createNestedBinaryExpr(recurmax, noComma) + createBinaryOp(noComma) + createExpression(recurmax, noComma, stmtDepth, canThrow); - case 5: + case 10: + case 11: return createValue(); - case 6: + case 12: return '(' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ')'; - case 7: + case 13: return createExpression(recurmax, noComma, stmtDepth, canThrow) + '?' + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + ':' + createExpression(recurmax, noComma, stmtDepth, canThrow); - case 8: + case 14: var nameLenBefore = VAR_NAMES.length; var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that. if (name === 'c') name = 'a'; @@ -513,9 +520,10 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { } VAR_NAMES.length = nameLenBefore; return s; - case 9: + case 15: + case 16: return createTypeofExpr(recurmax, stmtDepth, canThrow); - case 10: + case 17: // you could statically infer that this is just `Math`, regardless of the other expression // I don't think Uglify does this at this time... return ''+ @@ -523,7 +531,8 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { (rng(2) === 1 ? createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + '\n' : '') + 'return Math;\n' + '}'; - case 11: + case 18: + case 19: // more like a parser test but perhaps comment nodes mess up the analysis? // note: parens not needed for post-fix (since that's the default when ambiguous) // for prefix ops we need parens to prevent accidental syntax errors. @@ -546,13 +555,77 @@ function _createExpression(recurmax, noComma, stmtDepth, canThrow) { default: return '(--/* ignore */b)'; } - case 12: + case 20: + case 21: return createNestedBinaryExpr(recurmax, noComma); - case 13: + case 22: return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || a || 3).toString() "; - case 14: + case 23: return " /[abc4]/.test(((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + ") || b || 5).toString()) "; + case 24: + return " ((" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + + ") || " + rng(10) + ").toString()[" + + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "] "; + case 25: + return createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow); + case 26: + return createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow); + case 27: + return '(' + createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' + + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]) "; + case 28: + return '(' + createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '[' + + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "]) "; + case 29: + return '(' + createArrayLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + + SAFE_KEYS[rng(SAFE_KEYS.length)] + ") "; + case 30: + return '(' + createObjectLiteral(recurmax, COMMA_OK, stmtDepth, canThrow) + '.' + + SAFE_KEYS[rng(SAFE_KEYS.length)] + ") "; + } +} + +function createArrayLiteral(recurmax, noComma, stmtDepth, canThrow) { + recurmax--; + var arr = "["; + for (var i = rng(6); --i >= 0;) { + // in rare cases produce an array hole element + var element = rng(20) ? createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) : ""; + arr += element + ", "; + } + return arr + "]"; +} + +var SAFE_KEYS = [ + "length", + "foo", + "a", + "b", + "c", + "undefined", + "null", + "NaN", + "Infinity", + "in", + "var", +]; +var KEYS = [ + "''", + '"\t"', + '"-2"', + "0", + "1.5", + "3", +].concat(SAFE_KEYS); + +function createObjectLiteral(recurmax, noComma, stmtDepth, canThrow) { + recurmax--; + var obj = "({"; + for (var i = rng(6); --i >= 0;) { + var key = KEYS[rng(KEYS.length)]; + obj += key + ":(" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + "), "; } + return obj + "})"; } function createNestedBinaryExpr(recurmax, noComma) { diff --git a/test/ufuzz.json b/test/ufuzz.json index 2d871e87..214da8cd 100644 --- a/test/ufuzz.json +++ b/test/ufuzz.json @@ -4,6 +4,21 @@ "warnings": false } }, + { + "compress": { + "toplevel": true, + "warnings": false + }, + "mangle": { + "toplevel": true + } + }, + { + "compress": { + "warnings": false + }, + "mangleProperties": {} + }, { "compress": { "warnings": false @@ -22,6 +37,23 @@ "bracketize": true } }, + { + "compress": { + "passes": 3, + "properties": false, + "toplevel": true, + "warnings": false + }, + "mangle": { + "toplevel": true + }, + "mangleProperties": { + "ignore_quoted": true + }, + "output": { + "keep_quoted_props": true + } + }, { "compress": { "keep_fargs": false, -- 2.34.1