225
test/ufuzz.js
Normal file
225
test/ufuzz.js
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user