test_unit_common.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. "use strict";
  2. var Class = require("rtl.js").Class;
  3. var Code = require("js/Code.js");
  4. var ContextHierarchy = require("js/ContextHierarchy.js");
  5. var Errors = require("js/Errors.js");
  6. var oc = require("oc.js");
  7. var makeRTL = require("rtl_code.js").makeRTL;
  8. var Scope = require("js/Scope.js");
  9. var Stream = require("js/Stream.js");
  10. var Test = require("test.js");
  11. var TestError = Test.TestError;
  12. function context(grammar, source){
  13. return {grammar: grammar, source: source};
  14. }
  15. function pass(/*...*/){return Array.prototype.slice.call(arguments);}
  16. function fail(/*...*/){return Array.prototype.slice.call(arguments);}
  17. var TestModuleGenerator = Class.extend({
  18. init: function TestModuleGenerator(){},
  19. prolog: function(){return undefined;},
  20. epilog: function(){return undefined;}
  21. });
  22. var TestContext = Class.extend.call(ContextHierarchy.Root, {
  23. init: function TestContext(language){
  24. var rtl = new makeRTL(language.rtl);
  25. ContextHierarchy.Root.call(
  26. this,
  27. { codeGenerator: language.codeGenerator.nil,
  28. moduleGenerator: function(){return new TestModuleGenerator();},
  29. rtl: rtl,
  30. types: language.types,
  31. stdSymbols: language.stdSymbols
  32. });
  33. this.pushScope(new Scope.Module("test", language.stdSymbols));
  34. },
  35. qualifyScope: function(){return "";},
  36. handleMessage: function(){},
  37. handleExpression: function(){},
  38. handleLiteral: function(){}
  39. });
  40. function makeContext(language){return new TestContext(language);}
  41. function testWithSetup(setup, pass, fail){
  42. return function(){
  43. var test = setup();
  44. var i;
  45. for(i = 0; i < pass.length; ++i)
  46. test.expectOK(pass[i]);
  47. if (fail)
  48. for(i = 0; i < fail.length; ++i){
  49. var f = fail[i];
  50. test.expectError(f[0], f[1]);
  51. }
  52. };
  53. }
  54. function parseInContext(grammar, s, context){
  55. var stream = new Stream.Type(s);
  56. if (!grammar(stream, context) || !Stream.eof(stream))
  57. throw new Errors.Error("not parsed");
  58. }
  59. function runAndHandleErrors(action, s, handlerError){
  60. try {
  61. action(s);
  62. }
  63. catch (x){
  64. if (!(x instanceof Errors.Error))
  65. throw new Error("'" + s + "': " + x + "\n"
  66. + (x.stack ? x.stack : "(no stack)"));
  67. if (handlerError)
  68. handlerError(x);
  69. //else
  70. // throw x;
  71. // console.log(s + ": " + x);
  72. return false;
  73. }
  74. return true;
  75. }
  76. function setup(run){
  77. return {
  78. expectOK: function(s){
  79. function handleError(e){throw new TestError(s + "\n\t" + e);}
  80. if (!runAndHandleErrors(run, s, handleError))
  81. throw new TestError(s + ": not parsed");
  82. },
  83. expectError: function(s, error){
  84. function handleError(actualError){
  85. var sErr = actualError.toString();
  86. if (sErr != error)
  87. throw new TestError(s + "\n\texpected error: " + error + "\n\tgot: " + sErr );
  88. }
  89. if (runAndHandleErrors(run, s, handleError))
  90. throw new TestError(s + ": should not be parsed, expect error: " + error);
  91. }
  92. };
  93. }
  94. function parseUsingGrammar(parser, language, s, cxFactory){
  95. var baseContext = makeContext(language);
  96. var context = cxFactory ? cxFactory(baseContext) : baseContext;
  97. parseInContext(parser, s, context);
  98. context.currentScope().close();
  99. }
  100. function setupParser(parser, language, contextFactory){
  101. function parseImpl(s){
  102. return parseUsingGrammar(parser, language, s, contextFactory);
  103. }
  104. return setup(parseImpl);
  105. }
  106. function setupWithContext(grammar, contextGrammar, language, source){
  107. function innerMakeContext(){
  108. var context = makeContext(language);
  109. try {
  110. parseInContext(contextGrammar, source, context);
  111. }
  112. catch (x) {
  113. if (x instanceof Errors.Error)
  114. throw new TestError("setup error: " + x + "\n" + source);
  115. throw x;
  116. }
  117. return context;
  118. }
  119. return setupParser(grammar, language, innerMakeContext);
  120. }
  121. function testWithContext(context, contextGrammar, language, pass, fail){
  122. return testWithSetup(
  123. function(){return setupWithContext(context.grammar, contextGrammar, language, context.source);},
  124. pass,
  125. fail);
  126. }
  127. function testWithGrammar(parser, language, pass, fail){
  128. return testWithSetup(
  129. function(){return setupParser(parser, language);},
  130. pass,
  131. fail);
  132. }
  133. var TestContextWithModule = TestContext.extend({
  134. init: function(module, language){
  135. TestContext.prototype.init.call(this, language);
  136. this.__module = module;
  137. },
  138. findModule: function(){return this.__module;}
  139. });
  140. function testWithModule(src, language, pass, fail){
  141. var grammar = language.grammar;
  142. return testWithSetup(
  143. function(){
  144. var imported = oc.compileModule(grammar, new Stream.Type(src), makeContext(language));
  145. var module = imported.symbol().info();
  146. return setup(function(s){
  147. oc.compileModule(grammar,
  148. new Stream.Type(s),
  149. new TestContextWithModule(module, language));
  150. });},
  151. pass,
  152. fail);
  153. }
  154. function nthLine(s, n){
  155. var result = 0;
  156. while (n--)
  157. result = s.indexOf('\n', result) + 1;
  158. return result;
  159. }
  160. function assert(cond){
  161. if (!cond){
  162. var stack = new Error().stack;
  163. var from = nthLine(stack, 2);
  164. stack = stack.substring(from, stack.indexOf('\n', from));
  165. throw new TestError("assertion failed: " + stack);
  166. }
  167. }
  168. exports.assert = assert;
  169. exports.context = context;
  170. exports.pass = pass;
  171. exports.fail = fail;
  172. exports.setupParser = setupParser;
  173. exports.testWithContext = testWithContext;
  174. exports.testWithGrammar = testWithGrammar;
  175. exports.testWithModule = testWithModule;
  176. exports.testWithSetup = testWithSetup;