From: Alex Lam S.L Date: Sat, 1 Apr 2017 18:10:50 +0000 (+0800) Subject: upgrade fuzzer (#1754) X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=28ecea50a6ae0cc8c5bddca7764e5fd198a7730e;p=UglifyJS.git upgrade fuzzer (#1754) - configurable set of `minify()` options - test and report suspects upon failure - continue after failure if infinite iterations is specified --- diff --git a/test/ufuzz.js b/test/ufuzz.js index f0c0ea67..241e0439 100644 --- a/test/ufuzz.js +++ b/test/ufuzz.js @@ -12,7 +12,7 @@ stream._handle.setBlocking(true); }); -var minify = require("..").minify; +var UglifyJS = require(".."); var randomBytes = require("crypto").randomBytes; var sandbox = require("./sandbox"); @@ -116,7 +116,6 @@ for (var i = 2; i < process.argv.length; ++i) { console.log(': generate this many cases (if used must be first arg)'); console.log('-v: print every generated test case'); console.log('-V: print every 100th generated test case'); - console.log('-b: also run beautifier'); console.log('-t : generate this many toplevels per run (more take longer)'); console.log('-r : maximum recursion depth for generator (higher takes longer)'); console.log('-s1 : force the first level statement to be this one (see list below)'); @@ -630,7 +629,7 @@ function createVarName(maybe, dontStore) { function try_beautify(code, result) { try { - var beautified = minify(code, { + var beautified = UglifyJS.minify(code, { fromString: true, compress: false, mangle: false, @@ -652,7 +651,55 @@ function try_beautify(code, result) { console.log(code); } -function log() { +function infer_options(ctor) { + try { + ctor({ 0: 0 }); + } catch (e) { + return e.defs; + } +} + +var default_options = { + compress: infer_options(UglifyJS.Compressor), + mangle: { + "cache": null, + "eval": false, + "keep_fnames": false, + "screw_ie8": true, + "toplevel": false, + }, + output: infer_options(UglifyJS.OutputStream), +}; + +function log_suspects(minify_options, component) { + var options = component in minify_options ? minify_options[component] : true; + if (!options) return; + options = UglifyJS.defaults(options, default_options[component]); + var suspects = Object.keys(default_options[component]).filter(function(name) { + if (options[name]) { + var m = JSON.parse(JSON.stringify(minify_options)); + var o = JSON.parse(JSON.stringify(options)); + o[name] = false; + m[component] = o; + try { + var r = sandbox.run_code(UglifyJS.minify(original_code, m).code); + return sandbox.same_stdout(original_result, r); + } catch (e) { + console.log("Error testing options." + component + "." + name); + console.log(e); + } + } + }); + if (suspects.length > 0) { + console.log("Suspicious", component, "options:"); + suspects.forEach(function(name) { + console.log(" " + name); + }); + console.log(); + } +} + +function log(options) { if (!ok) console.log('\n\n\n\n\n\n!!!!!!!!!!\n\n\n'); console.log("//============================================================="); if (!ok) console.log("// !!!!!! Failed... round", round); @@ -674,9 +721,22 @@ function log() { console.log("// !!! uglify failed !!!"); console.log(uglify_code.stack); } - if (!ok) console.log("!!!!!! Failed... round", round); + console.log("minify(options):"); + options = JSON.parse(options); + console.log(options); + console.log(); + if (!ok) { + Object.keys(default_options).forEach(log_suspects.bind(null, options)); + console.log("!!!!!! Failed... round", round); + } } +var minify_options = require("./ufuzz.json").map(function(options) { + options.fromString = true; + return JSON.stringify(options); +}); +var original_code, original_result; +var uglify_code, uglify_result, ok; for (var round = 0; round < num_iterations; round++) { process.stdout.write(round + " of " + num_iterations + "\r"); @@ -684,27 +744,26 @@ for (var round = 0; round < num_iterations; round++) { loops = 0; funcs = 0; - var original_code = [ + original_code = [ "var a = 100, b = 10, c = 0;", createTopLevelCodes(rng(MAX_GENERATED_TOPLEVELS_PER_RUN) + 1), "console.log(null, a, b, c);" // preceding `null` makes for a cleaner output (empty string still shows up etc) ].join("\n"); - var uglify_code; - try { - uglify_code = minify(original_code, { - fromString: true, - }).code; - } catch (e) { - uglify_code = e; - } + minify_options.forEach(function(options) { + try { + uglify_code = UglifyJS.minify(original_code, JSON.parse(options)).code; + } catch (e) { + uglify_code = e; + } - var ok = typeof uglify_code == "string"; - if (ok) { - var original_result = sandbox.run_code(original_code); - var uglify_result = sandbox.run_code(uglify_code); - ok = sandbox.same_stdout(original_result, uglify_result); - } - if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(); - if (!ok) process.exit(1); + ok = typeof uglify_code == "string"; + if (ok) { + original_result = sandbox.run_code(original_code); + uglify_result = sandbox.run_code(uglify_code); + ok = sandbox.same_stdout(original_result, uglify_result); + } + if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options); + if (!ok && isFinite(num_iterations)) process.exit(1); + }); } diff --git a/test/ufuzz.json b/test/ufuzz.json new file mode 100644 index 00000000..8db03d2d --- /dev/null +++ b/test/ufuzz.json @@ -0,0 +1,34 @@ +[ + { + "compress": { + "warnings": false + } + }, + { + "compress": { + "warnings": false + }, + "mangle": false + }, + { + "compress": false, + "mangle": true + }, + { + "compress": false, + "mangle": false, + "output": { + "beautify": true, + "bracketize": true + } + }, + { + "compress": { + "keep_fargs": false, + "passes": 3, + "pure_getters": true, + "unsafe": true, + "warnings": false + } + } +]