run-tests.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #! /usr/bin/env node
  2. var U = require("../tools/node");
  3. var path = require("path");
  4. var fs = require("fs");
  5. var assert = require("assert");
  6. var sys = require("util");
  7. var tests_dir = path.dirname(module.filename);
  8. run_compress_tests();
  9. /* -----[ utils ]----- */
  10. function tmpl() {
  11. return U.string_template.apply(this, arguments);
  12. }
  13. function log() {
  14. var txt = tmpl.apply(this, arguments);
  15. sys.puts(txt);
  16. }
  17. function log_directory(dir) {
  18. log("*** Entering [{dir}]", { dir: dir });
  19. }
  20. function log_start_file(file) {
  21. log("--- {file}", { file: file });
  22. }
  23. function log_test(name) {
  24. log(" Running test [{name}]", { name: name });
  25. }
  26. function find_test_files(dir) {
  27. var files = fs.readdirSync(dir).filter(function(name){
  28. return /\.js$/i.test(name);
  29. });
  30. if (process.argv.length > 2) {
  31. var x = process.argv.slice(2);
  32. files = files.filter(function(f){
  33. return x.indexOf(f) >= 0;
  34. });
  35. }
  36. return files;
  37. }
  38. function test_directory(dir) {
  39. return path.resolve(tests_dir, dir);
  40. }
  41. function as_toplevel(input) {
  42. if (input instanceof U.AST_BlockStatement) input = input.body;
  43. else if (input instanceof U.AST_Statement) input = [ input ];
  44. else throw new Error("Unsupported input syntax");
  45. var toplevel = new U.AST_Toplevel({ body: input });
  46. toplevel.figure_out_scope();
  47. return toplevel;
  48. }
  49. function run_compress_tests() {
  50. var dir = test_directory("compress");
  51. log_directory("compress");
  52. var files = find_test_files(dir);
  53. function test_file(file) {
  54. log_start_file(file);
  55. function test_case(test) {
  56. log_test(test.name);
  57. var options = U.defaults(test.options, {
  58. warnings: false
  59. });
  60. var cmp = new U.Compressor(options, true);
  61. var expect = make_code(as_toplevel(test.expect), false);
  62. var input = as_toplevel(test.input);
  63. var input_code = make_code(test.input);
  64. var output = input.transform(cmp);
  65. output.figure_out_scope();
  66. output = make_code(output, false);
  67. if (expect != output) {
  68. log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
  69. input: input_code,
  70. output: output,
  71. expected: expect
  72. });
  73. }
  74. }
  75. var tests = parse_test(path.resolve(dir, file));
  76. for (var i in tests) if (tests.hasOwnProperty(i)) {
  77. test_case(tests[i]);
  78. }
  79. }
  80. files.forEach(function(file){
  81. test_file(file);
  82. });
  83. }
  84. function parse_test(file) {
  85. var script = fs.readFileSync(file, "utf8");
  86. var ast = U.parse(script, {
  87. filename: file
  88. });
  89. var tests = {};
  90. var tw = new U.TreeWalker(function(node, descend){
  91. if (node instanceof U.AST_LabeledStatement
  92. && tw.parent() instanceof U.AST_Toplevel) {
  93. var name = node.label.name;
  94. tests[name] = get_one_test(name, node.body);
  95. return true;
  96. }
  97. if (!(node instanceof U.AST_Toplevel)) croak(node);
  98. });
  99. ast.walk(tw);
  100. return tests;
  101. function croak(node) {
  102. throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
  103. file: file,
  104. line: node.start.line,
  105. col: node.start.col,
  106. code: make_code(node, false)
  107. }));
  108. }
  109. function get_one_test(name, block) {
  110. var test = { name: name, options: {} };
  111. var tw = new U.TreeWalker(function(node, descend){
  112. if (node instanceof U.AST_Assign) {
  113. if (!(node.left instanceof U.AST_SymbolRef)) {
  114. croak(node);
  115. }
  116. var name = node.left.name;
  117. test[name] = evaluate(node.right);
  118. return true;
  119. }
  120. if (node instanceof U.AST_LabeledStatement) {
  121. assert.ok(
  122. node.label.name == "input" || node.label.name == "expect",
  123. tmpl("Unsupported label {name} [{line},{col}]", {
  124. name: node.label.name,
  125. line: node.label.start.line,
  126. col: node.label.start.col
  127. })
  128. );
  129. var stat = node.body;
  130. if (stat instanceof U.AST_BlockStatement) {
  131. if (stat.body.length == 1) stat = stat.body[0];
  132. else if (stat.body.length == 0) stat = new U.AST_EmptyStatement();
  133. }
  134. test[node.label.name] = stat;
  135. return true;
  136. }
  137. });
  138. block.walk(tw);
  139. return test;
  140. };
  141. }
  142. function make_code(ast, beautify) {
  143. if (arguments.length == 1) beautify = true;
  144. var stream = U.OutputStream({ beautify: beautify });
  145. ast.print(stream);
  146. return stream.get();
  147. }
  148. function evaluate(code) {
  149. if (code instanceof U.AST_Node)
  150. code = make_code(code);
  151. return new Function("return(" + code + ")")();
  152. }