test_compile.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 readModule(src){
  40. var same_path_on_linux_and_win = src.replace(/\\/g, "/");
  41. return new oc.ReadModule(fs.readFileSync(src, "utf8"),
  42. same_path_on_linux_and_win);
  43. }
  44. function compile(src, language){
  45. var module = readModule(src);
  46. var errors = "";
  47. var result = oc.compile(module, language, function(e){errors += e;},
  48. extractOptions(module.content));
  49. if (errors)
  50. throw new Test.TestError(errors);
  51. return result;
  52. }
  53. function compileNodejs(src, dirs, language){
  54. language.rtl.nodejsModule = "test_rtl.js"; // make test results the same for oberon/eberon
  55. var subdir = path.basename(src);
  56. subdir = subdir.substr(0, subdir.length - path.extname(subdir).length);
  57. var outDir = path.join(dirs.output, subdir);
  58. fs.mkdirSync(outDir);
  59. var errors = "";
  60. nodejs.compile([src], language, function(e){errors += e;}, [], outDir);
  61. if (errors)
  62. throw new Test.TestError(errors);
  63. cmpDirs(path.join(dirs.expected, subdir), outDir);
  64. }
  65. function expectOk(src, dirs, grammar){
  66. var result = compile(src, grammar);
  67. var resultName = path.basename(src).replace(".ob", ".js");
  68. compareResults(result, resultName, dirs);
  69. }
  70. function expectError(src, dirs, language){
  71. var errors = "";
  72. try {
  73. oc.compile(readModule(src), language, function(e){errors += e + "\n";});
  74. }
  75. catch (e){
  76. errors += e;
  77. }
  78. if (!errors.length)
  79. throw new Test.TestError("compiler error expected");
  80. var resultName = path.basename(src).replace(".ob", ".txt");
  81. compareResults(errors, resultName, dirs);
  82. }
  83. function run(src, dirs, language){
  84. var result = compile(src, language);
  85. var resultName = path.basename(src).replace(".ob", ".js");
  86. var resultPath = path.join(dirs.output, resultName);
  87. fs.writeFileSync(resultPath, result);
  88. require(resultPath);
  89. }
  90. function expectRuntimeError(src, dirs, language){
  91. var error = "";
  92. try {
  93. run(src, dirs, language);
  94. }
  95. catch (x){
  96. error += x;
  97. }
  98. if (!error.length)
  99. throw new Test.TestError("runtime error expected");
  100. var resultName = path.basename(src).replace(".ob", ".txt");
  101. compareResults(error, resultName, dirs);
  102. }
  103. function makeTest(test, src, dirs, grammar){
  104. return function(){test(src, dirs, grammar);};
  105. }
  106. function makeTests(test, dirs, grammar){
  107. var output = dirs.output;
  108. if (fs.existsSync(output))
  109. rmTree(output);
  110. mkTree(output);
  111. var sources = fs.readdirSync(dirs.input);
  112. var tests = {};
  113. for(var i = 0; i < sources.length; ++i){
  114. var source = sources[i];
  115. var filePath = path.join(dirs.input, source);
  116. if (fs.statSync(filePath).isFile())
  117. tests[source] = makeTest(test, filePath, dirs, grammar);
  118. }
  119. return tests;
  120. }
  121. function mkTree(p){
  122. if (fs.existsSync(p))
  123. return;
  124. mkTree(path.dirname(p));
  125. fs.mkdirSync(p);
  126. }
  127. function rmTree(root){
  128. fs.readdirSync(root).forEach(function(file){
  129. var filePath = path.join(root, file);
  130. if (fs.statSync(filePath).isDirectory())
  131. rmTree(filePath);
  132. else
  133. fs.unlinkSync(filePath);
  134. });
  135. fs.rmdirSync(root);
  136. }
  137. function cmpDirs(expected, result){
  138. fs.readdirSync(expected).forEach(function(file){
  139. var expectedFile = path.join(expected, file);
  140. var resultFile = path.join(result, file);
  141. var expectedContent = fs.readFileSync(expectedFile, "utf8");
  142. var resultContent = fs.readFileSync(resultFile, "utf8");
  143. if ( normalizeLineEndings(expectedContent)
  144. != normalizeLineEndings(resultContent))
  145. throw new Test.TestError(
  146. "Files '" + expectedFile + "' and '"
  147. + resultFile + "' do not match.");
  148. });
  149. }
  150. var testDirs = {input: "input", output: "output", expected: "expected"};
  151. function makeTestDirs(subdir){
  152. if (!subdir)
  153. return testDirs;
  154. var result = {};
  155. for(var p in testDirs)
  156. result[p] = path.join(testDirs[p], subdir);
  157. return result;
  158. }
  159. function outputSubdir(dirs, subdir){
  160. var result = {};
  161. for(var p in dirs)
  162. result[p] = (p == "output") ? path.join(dirs[p], subdir) : dirs[p];
  163. return result;
  164. }
  165. function main(){
  166. var okDirs = makeTestDirs();
  167. var errDirs = makeTestDirs("errors");
  168. var errRuntimeDirs = makeTestDirs("errorsRT");
  169. var runDirs = makeTestDirs("run");
  170. var nodejsDirs = makeTestDirs("nodejs");
  171. var oberonDirs = makeTestDirs("oberon");
  172. var eberonDirs = makeTestDirs("eberon");
  173. var eberonRunDirs = makeTestDirs("eberon/run");
  174. var eberonErrDirs = makeTestDirs("eberon/errors");
  175. function makeCommonTests(language, subdir){
  176. return {
  177. "expect OK": makeTests(expectOk, outputSubdir(okDirs, subdir), language),
  178. "expect compile error": makeTests(expectError, outputSubdir(errDirs, subdir), language),
  179. "expect runtime error": makeTests(expectRuntimeError, outputSubdir(errRuntimeDirs, subdir), language),
  180. "run": makeTests(run, outputSubdir(runDirs, subdir), language),
  181. "nodejs": makeTests(compileNodejs, outputSubdir(nodejsDirs, subdir), language)
  182. };
  183. }
  184. var result =
  185. Test.run({"common": {"oberon": makeCommonTests(oberon, "oberon"),
  186. "eberon": makeCommonTests(eberon, "eberon")
  187. },
  188. "oberon": {"expect OK": makeTests(expectOk, oberonDirs, oberon)},
  189. "eberon": {"expect OK": makeTests(expectOk, eberonDirs, eberon),
  190. "run": makeTests(run, eberonRunDirs, eberon),
  191. "expect compile error": makeTests(expectError, eberonErrDirs, eberon)
  192. }
  193. });
  194. return result ? 0 : -1;
  195. }
  196. process.exit(main());