test_unit_common.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. "use strict";
  2. var Class = require("rtl.js").Class;
  3. var Code = require("js/Code.js");
  4. var Context = require("context.js");
  5. var Errors = require("js/Errors.js");
  6. var oc = require("oc.js");
  7. var RTL = require("rtl_code.js").RTL;
  8. var Scope = require("scope.js");
  9. var Stream = require("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 = Context.Context.extend({
  23. init: function TestContext(){
  24. Context.Context.prototype.init.call(
  25. this,
  26. Code.nullGenerator(),
  27. function(){return new TestModuleGenerator();},
  28. new RTL());
  29. this.pushScope(new Scope.Module("test"));
  30. },
  31. qualifyScope: function(){return "";}
  32. });
  33. function makeContext(){return new TestContext();}
  34. function testWithSetup(setup, pass, fail){
  35. return function(){
  36. var test = setup();
  37. var i;
  38. for(i = 0; i < pass.length; ++i)
  39. test.expectOK(pass[i]);
  40. if (fail)
  41. for(i = 0; i < fail.length; ++i){
  42. var f = fail[i];
  43. test.expectError(f[0], f[1]);
  44. }
  45. };
  46. }
  47. function parseInContext(grammar, s, context){
  48. var stream = Stream.make(s);
  49. if (!grammar(stream, context) || !Stream.eof(stream))
  50. throw new Errors.Error("not parsed");
  51. }
  52. function runAndHandleErrors(action, s, handlerError){
  53. try {
  54. action(s);
  55. }
  56. catch (x){
  57. if (!(x instanceof Errors.Error))
  58. throw new Error("'" + s + "': " + x + "\n"
  59. + (x.stack ? x.stack : "(no stack)"));
  60. if (handlerError)
  61. handlerError(x);
  62. //else
  63. // throw x;
  64. // console.log(s + ": " + x);
  65. return false;
  66. }
  67. return true;
  68. }
  69. function setup(run){
  70. return {
  71. expectOK: function(s){
  72. function handleError(e){throw new TestError(s + "\n\t" + e);}
  73. if (!runAndHandleErrors(run, s, handleError))
  74. throw new TestError(s + ": not parsed");
  75. },
  76. expectError: function(s, error){
  77. function handleError(actualError){
  78. var sErr = actualError.toString();
  79. if (sErr != error)
  80. throw new TestError(s + "\n\texpected error: " + error + "\n\tgot: " + sErr );
  81. }
  82. if (runAndHandleErrors(run, s, handleError))
  83. throw new TestError(s + ": should not be parsed, expect error: " + error);
  84. }
  85. };
  86. }
  87. function parseUsingGrammar(grammar, s, cxFactory){
  88. var baseContext = makeContext();
  89. var context = cxFactory ? cxFactory(baseContext) : baseContext;
  90. parseInContext(grammar, s, context);
  91. context.currentScope().close();
  92. }
  93. function setupParser(parser, contextFactory){
  94. function parseImpl(s){
  95. return parseUsingGrammar(parser, s, contextFactory);
  96. }
  97. return setup(parseImpl);
  98. }
  99. function setupWithContext(grammar, contextGrammar, source){
  100. function innerMakeContext(){
  101. var context = makeContext();
  102. try {
  103. parseInContext(contextGrammar, source, context);
  104. }
  105. catch (x) {
  106. if (x instanceof Errors.Error)
  107. throw new TestError("setup error: " + x + "\n" + source);
  108. throw x;
  109. }
  110. return context;
  111. }
  112. return setupParser(grammar, innerMakeContext);
  113. }
  114. function testWithContext(context, contextGrammar, pass, fail){
  115. return testWithSetup(
  116. function(){return setupWithContext(context.grammar, contextGrammar, context.source);},
  117. pass,
  118. fail);
  119. }
  120. function testWithGrammar(grammar, pass, fail){
  121. return testWithSetup(
  122. function(){return setupParser(grammar);},
  123. pass,
  124. fail);
  125. }
  126. var TestContextWithModule = TestContext.extend({
  127. init: function(module){
  128. TestContext.prototype.init.call(this);
  129. this.__module = module;
  130. },
  131. findModule: function(){return this.__module;}
  132. });
  133. function testWithModule(src, grammar, pass, fail){
  134. return testWithSetup(
  135. function(){
  136. var imported = oc.compileModule(grammar, Stream.make(src), makeContext());
  137. var module = imported.symbol().info();
  138. return setup(function(s){
  139. oc.compileModule(grammar,
  140. Stream.make(s),
  141. new TestContextWithModule(module));
  142. });},
  143. pass,
  144. fail);
  145. }
  146. exports.context = context;
  147. exports.pass = pass;
  148. exports.fail = fail;
  149. exports.makeContext = makeContext;
  150. exports.setupParser = setupParser;
  151. exports.testWithContext = testWithContext;
  152. exports.testWithGrammar = testWithGrammar;
  153. exports.testWithModule = testWithModule;
  154. exports.testWithSetup = testWithSetup;