test_compile.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. "use strict";
  2. var nodejs = require("nodejs.js");
  3. var oc = require("oc");
  4. var oberon = require("oberon/oberon_grammar.js").language;
  5. var eberon = require("eberon/eberon_grammar.js").language;
  6. var fs = require("fs");
  7. var path = require("path");
  8. var Test = require("test.js");
  9. function normalizeLineEndings(text){
  10. return text.replace(/\r\n/g, '\n')
  11. .replace(/\s+$/,''); // ending spaces
  12. }
  13. function filterOutScopes(text){
  14. return text.replace(/.*\$scope =.+\n/g, "")
  15. .replace(/, \$scope\)/g, ")");
  16. }
  17. function filterOutRtlCode(text){
  18. var prefix = "var RTL$ = {";
  19. if (text.substr(0, prefix.length) != prefix)
  20. return text;
  21. var suffix = "\n};";
  22. var end = text.indexOf(suffix);
  23. if (end == -1)
  24. return text;
  25. return "<rtl code>" + text.substr(end + suffix.length);
  26. }
  27. function compareResults(result, name, dirs){
  28. result = filterOutRtlCode(result);
  29. result = filterOutScopes(result);
  30. fs.writeFileSync(path.join(dirs.output, name), result);
  31. var expected = fs.readFileSync(path.join(dirs.expected, name), "utf8");
  32. if (normalizeLineEndings(result) != normalizeLineEndings(expected))
  33. throw new Test.TestError("Failed");
  34. }
  35. function extractOptions(text){
  36. var match = text.match(/\(\*options:({.*})\*\)/);
  37. return match ? JSON.parse(match[1]) : null;
  38. }
  39. function compile(src, language){
  40. var text = fs.readFileSync(src, "utf8");
  41. var errors = "";
  42. var result = oc.compile(text, language, function(e){errors += e;}, extractOptions(text));
  43. if (errors)
  44. throw new Test.TestError(errors);
  45. return result;
  46. }
  47. function compileNodejs(src, dirs, language){
  48. language.rtl.nodejsModule = "test_rtl.js"; // make test results the same for oberon/eberon
  49. var subdir = path.basename(src);
  50. subdir = subdir.substr(0, subdir.length - path.extname(subdir).length);
  51. var outDir = path.join(dirs.output, subdir);
  52. fs.mkdirSync(outDir);
  53. var errors = "";
  54. nodejs.compile([src], language, function(e){errors += e;}, [], outDir);
  55. if (errors)
  56. throw new Test.TestError(errors);
  57. cmpDirs(path.join(dirs.expected, subdir), outDir);
  58. }
  59. function expectOk(src, dirs, grammar){
  60. var result = compile(src, grammar);
  61. var resultName = path.basename(src).replace(".ob", ".js");
  62. compareResults(result, resultName, dirs);
  63. }
  64. function expectError(src, dirs, language){
  65. var text = fs.readFileSync(src, "utf8");
  66. var errors = "";
  67. try {
  68. oc.compile(text, language, function(e){errors += e + "\n";});
  69. }
  70. catch (e){
  71. errors += e;
  72. }
  73. if (!errors.length)
  74. throw new Test.TestError("compiler error expected");
  75. var resultName = path.basename(src).replace(".ob", ".txt");
  76. compareResults(errors, resultName, dirs);
  77. }
  78. function run(src, dirs, language){
  79. var result = compile(src, language);
  80. var resultName = path.basename(src).replace(".ob", ".js");
  81. var resultPath = path.join(dirs.output, resultName);
  82. fs.writeFileSync(resultPath, result);
  83. require(resultPath);
  84. }
  85. function expectRuntimeError(src, dirs, language){
  86. var error = "";
  87. try {
  88. run(src, dirs, language);
  89. }
  90. catch (x){
  91. error += x;
  92. }
  93. if (!error.length)
  94. throw new Test.TestError("runtime error expected");
  95. var resultName = path.basename(src).replace(".ob", ".txt");
  96. compareResults(error, resultName, dirs);
  97. }
  98. function makeTest(test, src, dirs, grammar){
  99. return function(){test(src, dirs, grammar);};
  100. }
  101. function makeTests(test, dirs, grammar){
  102. var output = dirs.output;
  103. if (fs.existsSync(output))
  104. rmTree(output);
  105. mkTree(output);
  106. var sources = fs.readdirSync(dirs.input);
  107. var tests = {};
  108. for(var i = 0; i < sources.length; ++i){
  109. var source = sources[i];
  110. var filePath = path.join(dirs.input, source);
  111. if (fs.statSync(filePath).isFile())
  112. tests[source] = makeTest(test, filePath, dirs, grammar);
  113. }
  114. return tests;
  115. }
  116. function mkTree(p){
  117. if (fs.existsSync(p))
  118. return;
  119. mkTree(path.dirname(p));
  120. fs.mkdirSync(p);
  121. }
  122. function rmTree(root){
  123. fs.readdirSync(root).forEach(function(file){
  124. var filePath = path.join(root, file);
  125. if (fs.statSync(filePath).isDirectory())
  126. rmTree(filePath);
  127. else
  128. fs.unlinkSync(filePath);
  129. });
  130. fs.rmdirSync(root);
  131. }
  132. function cmpDirs(expected, result){
  133. fs.readdirSync(expected).forEach(function(file){
  134. var expectedFile = path.join(expected, file);
  135. var resultFile = path.join(result, file);
  136. var expectedContent = fs.readFileSync(expectedFile, "utf8");
  137. var resultContent = fs.readFileSync(resultFile, "utf8");
  138. if ( normalizeLineEndings(expectedContent)
  139. != normalizeLineEndings(resultContent))
  140. throw new Test.TestError(
  141. "Files '" + expectedFile + "' and '"
  142. + resultFile + "' do not match.");
  143. });
  144. }
  145. var testDirs = {input: "input", output: "output", expected: "expected"};
  146. function makeTestDirs(subdir){
  147. if (!subdir)
  148. return testDirs;
  149. var result = {};
  150. for(var p in testDirs)
  151. result[p] = path.join(testDirs[p], subdir);
  152. return result;
  153. }
  154. function outputSubdir(dirs, subdir){
  155. var result = {};
  156. for(var p in dirs)
  157. result[p] = (p == "output") ? path.join(dirs[p], subdir) : dirs[p];
  158. return result;
  159. }
  160. function main(){
  161. var okDirs = makeTestDirs();
  162. var errDirs = makeTestDirs("errors");
  163. var errRuntimeDirs = makeTestDirs("errorsRT");
  164. var runDirs = makeTestDirs("run");
  165. var nodejsDirs = makeTestDirs("nodejs");
  166. var oberonDirs = makeTestDirs("oberon");
  167. var eberonDirs = makeTestDirs("eberon");
  168. var eberonRunDirs = makeTestDirs("eberon/run");
  169. var eberonErrDirs = makeTestDirs("eberon/errors");
  170. function makeCommonTests(language, subdir){
  171. return {
  172. "expect OK": makeTests(expectOk, outputSubdir(okDirs, subdir), language),
  173. "expect compile error": makeTests(expectError, outputSubdir(errDirs, subdir), language),
  174. "expect runtime error": makeTests(expectRuntimeError, outputSubdir(errRuntimeDirs, subdir), language),
  175. "run": makeTests(run, outputSubdir(runDirs, subdir), language),
  176. "nodejs": makeTests(compileNodejs, outputSubdir(nodejsDirs, subdir), language)
  177. };
  178. }
  179. var result =
  180. Test.run({"common": {"oberon": makeCommonTests(oberon, "oberon"),
  181. "eberon": makeCommonTests(eberon, "eberon")
  182. },
  183. "oberon": {"expect OK": makeTests(expectOk, oberonDirs, oberon)},
  184. "eberon": {"expect OK": makeTests(expectOk, eberonDirs, eberon),
  185. "run": makeTests(run, eberonRunDirs, eberon),
  186. "expect compile error": makeTests(expectError, eberonErrDirs, eberon)
  187. }
  188. });
  189. return result ? 0 : -1;
  190. }
  191. process.exit(main());