aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2017-03-25 01:46:12 +0800
committerGitHub <noreply@github.com>2017-03-25 01:46:12 +0800
commitb1abe92e1aface2ec3d1c3666f8674e120f3b487 (patch)
treee20e909fe144c04104f83b01276758bbe730b5b9 /test
parentb454ce667eb8d9179c74532f308484bdae5392f5 (diff)
downloadtracifyjs-b1abe92e1aface2ec3d1c3666f8674e120f3b487.tar.gz
tracifyjs-b1abe92e1aface2ec3d1c3666f8674e120f3b487.zip
introduce ufuzz.js (#1655)
closes #1647
Diffstat (limited to 'test')
-rw-r--r--test/ufuzz.js225
1 files changed, 225 insertions, 0 deletions
diff --git a/test/ufuzz.js b/test/ufuzz.js
new file mode 100644
index 00000000..ac2ded7c
--- /dev/null
+++ b/test/ufuzz.js
@@ -0,0 +1,225 @@
+// ufuzz.js
+// derived from https://github.com/qfox/uglyfuzzer by Peter van der Zee
+"use strict";
+
+// workaround for tty output truncation upon process.exit()
+[process.stdout, process.stderr].forEach(function(stream){
+ if (stream._handle && stream._handle.setBlocking)
+ stream._handle.setBlocking(true);
+});
+
+var vm = require("vm");
+var minify = require("..").minify;
+
+function run_code(code) {
+ var stdout = "";
+ var original_write = process.stdout.write;
+ process.stdout.write = function(chunk) {
+ stdout += chunk;
+ };
+ try {
+ new vm.Script(code).runInNewContext({ console: console }, { timeout: 5000 });
+ return stdout;
+ } catch (ex) {
+ return ex;
+ } finally {
+ process.stdout.write = original_write;
+ }
+}
+
+function rng(max) {
+ return Math.floor(max * Math.random());
+}
+
+function createFunctionDecls(n, recurmax) {
+ if (--recurmax < 0) { return ';'; }
+ var s = '';
+ while (--n > 0) {
+ s += createFunctionDecl(recurmax) + '\n';
+ }
+ return s;
+}
+
+var funcs = 0;
+function createFunctionDecl(recurmax) {
+ if (--recurmax < 0) { return ';'; }
+ var func = funcs++;
+ return 'function f' + func + '(){' + createStatements(3, recurmax) + '}\nf' + func + '();';
+}
+
+function createStatements(n, recurmax) {
+ if (--recurmax < 0) { return ';'; }
+ var s = '';
+ while (--n > 0) {
+ s += createStatement(recurmax);
+ }
+ return s;
+}
+
+var loops = 0;
+function createStatement(recurmax) {
+ var loop = ++loops;
+ if (--recurmax < 0) { return ';'; }
+ switch (rng(7)) {
+ case 0:
+ return '{' + createStatement(recurmax) + '}';
+ case 1:
+ return 'if (' + createExpression(recurmax) + ')' + createStatement(recurmax);
+ case 2:
+ return '{var brake' + loop + ' = 5; do {' + createStatement(recurmax) + '} while ((' + createExpression(recurmax) + ') && --brake' + loop + ' > 0);}';
+ case 3:
+ return '{var brake' + loop + ' = 5; while ((' + createExpression(recurmax) + ') && --brake' + loop + ' > 0)' + createStatement(recurmax) + '}';
+ case 4:
+ return 'for (var brake' + loop + ' = 5; (' + createExpression(recurmax) + ') && brake' + loop + ' > 0; --brake' + loop + ')' + createStatement(recurmax);
+ case 5:
+ return ';';
+ case 6:
+ return createExpression() + ';';
+ }
+}
+
+function createExpression(recurmax) {
+ if (--recurmax < 0) { return '0'; }
+ switch (rng(8)) {
+ case 0:
+ return '(' + createUnaryOp() + 'a)';
+ case 1:
+ return '(a' + (Math.random() > 0.5 ? '++' : '--') + ')';
+ case 2:
+ return '(b ' + createAssignment() + ' a)';
+ case 3:
+ return '(' + Math.random() + ' > 0.5 ? a : b)';
+ case 4:
+ return createExpression(recurmax) + createBinaryOp() + createExpression(recurmax);
+ case 5:
+ return createValue();
+ case 6:
+ return '(' + createExpression(recurmax) + ')';
+ case 7:
+ return createExpression(recurmax) + '?(' + createExpression(recurmax) + '):(' + createExpression(recurmax) + ')';
+ }
+}
+
+function createValue() {
+ var values = [
+ 'true',
+ 'false',
+ '22',
+ '0',
+ '(-1)',
+ 'NaN',
+ 'undefined',
+ 'null',
+ '"foo"',
+ '"bar"' ];
+ return values[rng(values.length)];
+}
+
+function createBinaryOp() {
+ switch (rng(6)) {
+ case 0:
+ return '+';
+ case 1:
+ return '-';
+ case 2:
+ return ',';
+ case 3:
+ return '&&';
+ case 4:
+ return '||';
+ case 5:
+ return '^';
+ }
+}
+
+function createAssignment() {
+ switch (rng(4)) {
+ case 0:
+ return '=';
+ case 1:
+ return '-=';
+ case 2:
+ return '^=';
+ case 3:
+ return '+=';
+ }
+}
+
+function createUnaryOp() {
+ switch (rng(4)) {
+ case 0:
+ return '--';
+ case 1:
+ return '++';
+ case 2:
+ return '~';
+ case 3:
+ return '!';
+ }
+}
+
+function log() {
+ console.log("//=============================================================");
+ console.log("// original code");
+ console.log("//");
+ console.log(original_code);
+ console.log();
+ console.log();
+ console.log("//-------------------------------------------------------------");
+ console.log("// original code (beautify'd)");
+ console.log("//");
+ console.log(beautify_code);
+ console.log();
+ console.log();
+ console.log("//-------------------------------------------------------------");
+ console.log("// uglified code");
+ console.log("//");
+ console.log(uglify_code);
+ console.log();
+ console.log();
+ console.log("original result:");
+ console.log(original_result);
+ console.log("beautified result:");
+ console.log(beautify_result);
+ console.log("uglified result:");
+ console.log(uglify_result);
+}
+
+var num_iterations = +process.argv[2] || 1/0;
+var verbose = !!process.argv[3];
+for (var round = 0; round < num_iterations; round++) {
+ process.stdout.write(round + " of " + num_iterations + "\r");
+ var original_code = [
+ "var a = 100, b = 10;",
+ createFunctionDecls(rng(3) + 1, 10),
+ "console.log(a, b);"
+ ].join("\n");
+ var beautify_code = minify(original_code, {
+ fromString: true,
+ mangle: false,
+ compress: false,
+ output: {
+ beautify: true,
+ bracketize: true,
+ },
+ }).code;
+
+ var uglify_code = minify(beautify_code, {
+ fromString: true,
+ mangle: false,
+ compress: {
+ passes: 3,
+ },
+ output: {
+ beautify: true,
+ bracketize: true,
+ },
+ }).code;
+
+ var original_result = run_code(original_code);
+ var beautify_result = run_code(beautify_code);
+ var uglify_result = run_code(uglify_code);
+ var ok = original_result == beautify_result && original_result == uglify_result;
+ if (verbose || !ok) log();
+ if (!ok) process.exit(1);
+}