[Pkg-javascript-commits] [uglifyjs] 08/26: Added generative testing for AST conversions.

Jonas Smedegaard dr at jones.dk
Tue May 19 00:02:21 UTC 2015


This is an automated email from the git hooks/post-receive script.

js pushed a commit to tag v2.4.16
in repository uglifyjs.

commit b467a3c877c8a953bf945d892a5c1bdb9573336c
Author: Ingvar Stepanyan <me at rreverser.com>
Date:   Sun Aug 3 20:48:59 2014 +0300

    Added generative testing for AST conversions.
---
 lib/mozilla-ast.js  |  11 +++---
 package.json        |  12 ++++--
 test/mozilla-ast.js | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/run-tests.js   |   6 +++
 4 files changed, 123 insertions(+), 9 deletions(-)

diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js
index 7f0995c..602ef0e 100644
--- a/lib/mozilla-ast.js
+++ b/lib/mozilla-ast.js
@@ -303,12 +303,11 @@
     });
 
     def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
-        var key;
-        if (is_identifier_string(M.key) && !RESERVED_WORDS(M.key)) {
-            key = {type: "Identifier", name: M.key};
-        } else {
-            key = {type: "Literal", value: M.key};
-        }
+        var key = (
+            is_identifier(M.key)
+            ? {type: "Identifier", name: M.key}
+            : {type: "Literal", value: M.key}
+        );
         var kind;
         if (M instanceof AST_ObjectKeyVal) {
             kind = "init";
diff --git a/package.json b/package.json
index 26d8f76..90d587f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
-    "name": "uglify-js",
-    "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
+  "name": "uglify-js",
+  "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
     "homepage": "http://lisperator.net/uglifyjs",
     "main": "tools/node.js",
     "version": "2.4.15",
@@ -17,9 +17,15 @@
     "dependencies": {
         "async"      : "~0.2.6",
         "source-map" : "0.1.34",
-        "optimist"   : "~0.3.5",
+        "optimist": "~0.3.5",
         "uglify-to-browserify": "~1.0.0"
     },
+    "devDependencies": {
+        "acorn": "~0.6.0",
+        "escodegen": "~1.3.3",
+        "esfuzz": "~0.3.1",
+        "estraverse": "~1.5.1"
+    },
     "browserify": {
         "transform": [ "uglify-to-browserify" ]
     },
diff --git a/test/mozilla-ast.js b/test/mozilla-ast.js
new file mode 100644
index 0000000..0262867
--- /dev/null
+++ b/test/mozilla-ast.js
@@ -0,0 +1,103 @@
+// Testing UglifyJS <-> SpiderMonkey AST conversion
+// through generative testing.
+
+var UglifyJS = require(".."),
+    escodegen = require("escodegen"),
+    esfuzz = require("esfuzz"),
+    estraverse = require("estraverse"),
+    prefix = Array(20).join("\b") + "    ";
+
+// Normalizes input AST for UglifyJS in order to get correct comparison.
+
+function normalizeInput(ast) {
+    return estraverse.replace(ast, {
+        enter: function(node, parent) {
+            switch (node.type) {
+                // Internally mark all the properties with semi-standard type "Property".
+                case "ObjectExpression":
+                    node.properties.forEach(function (property) {
+                        property.type = "Property";
+                    });
+                    break;
+
+                // Since UglifyJS doesn"t recognize different types of property keys,
+                // decision on SpiderMonkey node type is based on check whether key
+                // can be valid identifier or not - so we do in input AST.
+                case "Property":
+                    var key = node.key;
+                    if (key.type === "Literal" && typeof key.value === "string" && UglifyJS.is_identifier(key.value)) {
+                        node.key = {
+                            type: "Identifier",
+                            name: key.value
+                        };
+                    } else if (key.type === "Identifier" && !UglifyJS.is_identifier(key.name)) {
+                        node.key = {
+                            type: "Literal",
+                            value: key.name
+                        };
+                    }
+                    break;
+
+                // UglifyJS internally flattens all the expression sequences - either
+                // to one element (if sequence contains only one element) or flat list.
+                case "SequenceExpression":
+                    node.expressions = node.expressions.reduce(function flatten(list, expr) {
+                        return list.concat(expr.type === "SequenceExpression" ? expr.expressions.reduce(flatten, []) : [expr]);
+                    }, []);
+                    if (node.expressions.length === 1) {
+                        return node.expressions[0];
+                    }
+                    break;
+            }
+        }
+    });
+}
+
+module.exports = function(options) {
+    console.log("--- UglifyJS <-> Mozilla AST conversion");
+
+    for (var counter = 0; counter < options.iterations; counter++) {
+        process.stdout.write(prefix + counter + "/" + options.iterations);
+
+        var ast1 = normalizeInput(esfuzz.generate({
+            maxDepth: options.maxDepth
+        }));
+        
+        var ast2 =
+            UglifyJS
+            .AST_Node
+            .from_mozilla_ast(ast1)
+            .to_mozilla_ast();
+
+        var astPair = [
+            {name: 'expected', value: ast1},
+            {name: 'actual', value: ast2}
+        ];
+
+        var jsPair = astPair.map(function(item) {
+            return {
+                name: item.name,
+                value: escodegen.generate(item.value)
+            }
+        });
+
+        if (jsPair[0].value !== jsPair[1].value) {
+            var fs = require("fs");
+            var acorn = require("acorn");
+
+            fs.existsSync("tmp") || fs.mkdirSync("tmp");
+
+            jsPair.forEach(function (item) {
+                var fileName = "tmp/dump_" + item.name;
+                var ast = acorn.parse(item.value);
+                fs.writeFileSync(fileName + ".js", item.value);
+                fs.writeFileSync(fileName + ".json", JSON.stringify(ast, null, 2));
+            });
+
+            process.stdout.write("\n");
+            throw new Error("Got different outputs, check out tmp/dump_*.{js,json} for codes and ASTs.");
+        }
+    }
+
+    process.stdout.write(prefix + "Probability of error is less than " + (100 / options.iterations) + "%, stopping.\n");
+};
\ No newline at end of file
diff --git a/test/run-tests.js b/test/run-tests.js
index f8e88d4..94bf6ad 100755
--- a/test/run-tests.js
+++ b/test/run-tests.js
@@ -17,6 +17,12 @@ if (failures) {
     process.exit(1);
 }
 
+var run_ast_conversion_tests = require("./mozilla-ast");
+
+run_ast_conversion_tests({
+    iterations: 1000
+});
+
 /* -----[ utils ]----- */
 
 function tmpl() {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git



More information about the Pkg-javascript-commits mailing list