Index: test/promises-aplus/lib/mocha.js |
diff --git a/test/promises-aplus/lib/mocha.js b/test/promises-aplus/lib/mocha.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..24d294ef8f829889fbcdccf1a9893f92635c7aea |
--- /dev/null |
+++ b/test/promises-aplus/lib/mocha.js |
@@ -0,0 +1,264 @@ |
+// Copyright 2014 the V8 project authors. All rights reserved. |
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following |
+// disclaimer in the documentation and/or other materials provided |
+// with the distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived |
+// from this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+// This file emulates Mocha test framework used in promises-aplus tests. |
+ |
+var describe; |
+var it; |
+var specify; |
+var before; |
+var after; |
+var beforeEach; |
+var afterEach; |
+var RunAllTests; |
+ |
+var assert = require('assert'); |
+ |
+(function() { |
+var TIMEOUT = 1000; |
+ |
+function PostMicrotask(fn) { |
+ var o = {}; |
+ Object.observe(o, function() { |
+ fn(); |
+ }); |
+ // Change something to enqueue a microtask. |
+ o.x = 'hello'; |
+} |
+ |
+var context = { |
+ beingDescribed: undefined, |
+ currentSuiteIndex: 0, |
+ suites: [] |
+}; |
+ |
+function Run() { |
+ function current() { |
+ while (context.currentSuiteIndex < context.suites.length && |
+ context.suites[context.currentSuiteIndex].hasRun) { |
+ ++context.currentSuiteIndex; |
+ } |
+ if (context.suites.length == context.currentSuiteIndex) { |
+ return undefined; |
+ } |
+ return context.suites[context.currentSuiteIndex]; |
+ } |
+ var suite = current(); |
+ if (!suite) { |
+ // done |
+ print('All tests have run.'); |
+ return; |
+ } |
+ suite.Run(); |
+} |
+ |
+RunAllTests = function() { |
+ context.currentSuiteIndex = 0; |
+ var numRegularTestCases = 0; |
+ for (var i = 0; i < context.suites.length; ++i) { |
+ numRegularTestCases += context.suites[i].numRegularTestCases(); |
+ } |
+ print(context.suites.length + ' suites and ' + numRegularTestCases + |
+ ' test cases are found'); |
+ Run(); |
+}; |
+ |
+function TestCase(name, before, fn, after, isRegular) { |
+ this.name = name; |
+ this.before = before; |
+ this.fn = fn; |
+ this.after = after; |
+ this.isRegular = isRegular; |
+ this.hasDone = false; |
+} |
+ |
+TestCase.prototype.RunFunction = function(suite, fn, postAction) { |
+ if (!fn) { |
+ postAction(); |
+ return; |
+ } |
+ try { |
+ if (fn.length === 0) { |
+ // synchronous |
+ fn(); |
+ postAction(); |
+ } else { |
+ // asynchronous |
+ fn(postAction); |
+ } |
+ } catch (e) { |
+ suite.ReportError(this, e); |
+ } |
+} |
+ |
+TestCase.prototype.MarkAsDone = function() { |
+ this.hasDone = true; |
+ clearTimeout(this.timer); |
+} |
+ |
+TestCase.prototype.Run = function(suite, postAction) { |
+ print('Running ' + suite.description + '#' + this.name + ' ...'); |
+ assert.clear(); |
+ |
+ this.timer = setTimeout(function() { |
+ suite.ReportError(this, Error('timeout')); |
+ }.bind(this), TIMEOUT); |
+ |
+ this.RunFunction(suite, this.before, function(e) { |
+ if (this.hasDone) { |
+ return; |
+ } |
+ if (e instanceof Error) { |
+ return suite.ReportError(this, e); |
+ } |
+ if (assert.fails.length > 0) { |
+ return suite.ReportError(this, assert.fails[0]); |
+ } |
+ this.RunFunction(suite, this.fn, function(e) { |
+ if (this.hasDone) { |
+ return; |
+ } |
+ if (e instanceof Error) { |
+ return suite.ReportError(this, e); |
+ } |
+ if (assert.fails.length > 0) { |
+ return suite.ReportError(this, assert.fails[0]); |
+ } |
+ this.RunFunction(suite, this.after, function(e) { |
+ if (this.hasDone) { |
+ return; |
+ } |
+ if (e instanceof Error) { |
+ return suite.ReportError(this, e); |
+ } |
+ if (assert.fails.length > 0) { |
+ return suite.ReportError(this, assert.fails[0]); |
+ } |
+ this.MarkAsDone(); |
+ if (this.isRegular) { |
+ print('PASS: ' + suite.description + '#' + this.name); |
+ } |
+ PostMicrotask(postAction); |
+ }.bind(this)); |
+ }.bind(this)); |
+ }.bind(this)); |
+}; |
+ |
+function TestSuite(described) { |
+ this.description = described.description; |
+ this.cases = []; |
+ this.currentIndex = 0; |
+ this.hasRun = false; |
+ |
+ if (described.before) { |
+ this.cases.push(new TestCase(this.description + ' :before', undefined, |
+ described.before, undefined, false)); |
+ } |
+ for (var i = 0; i < described.cases.length; ++i) { |
+ this.cases.push(new TestCase(described.cases[i].description, |
+ described.beforeEach, |
+ described.cases[i].fn, |
+ described.afterEach, |
+ true)); |
+ } |
+ if (described.after) { |
+ this.cases.push(new TestCase(this.description + ' :after', |
+ undefined, described.after, undefined, false)); |
+ } |
+} |
+ |
+TestSuite.prototype.Run = function() { |
+ this.hasRun = this.currentIndex === this.cases.length; |
+ if (this.hasRun) { |
+ PostMicrotask(Run); |
+ return; |
+ } |
+ |
+ // TestCase.prototype.Run cannot throw an exception. |
+ this.cases[this.currentIndex].Run(this, function() { |
+ ++this.currentIndex; |
+ PostMicrotask(Run); |
+ }.bind(this)); |
+}; |
+ |
+TestSuite.prototype.numRegularTestCases = function() { |
+ var n = 0; |
+ for (var i = 0; i < this.cases.length; ++i) { |
+ if (this.cases[i].isRegular) { |
+ ++n; |
+ } |
+ } |
+ return n; |
+} |
+ |
+TestSuite.prototype.ReportError = function(testCase, e) { |
+ if (testCase.hasDone) { |
+ return; |
+ } |
+ testCase.MarkAsDone(); |
+ this.hasRun = this.currentIndex === this.cases.length; |
+ print('FAIL: ' + this.description + '#' + testCase.name + ': ' + |
+ e.name + ' (' + e.message + ')'); |
+ ++this.currentIndex; |
+ PostMicrotask(Run); |
+}; |
+ |
+describe = function(description, fn) { |
+ var parent = context.beingDescribed; |
+ var incomplete = { |
+ cases: [], |
+ description: parent ? parent.description + ' ' + description : description, |
+ parent: parent, |
+ }; |
+ context.beingDescribed = incomplete; |
+ fn(); |
+ context.beingDescribed = parent; |
+ |
+ context.suites.push(new TestSuite(incomplete)); |
+} |
+ |
+specify = it = function(description, fn) { |
+ context.beingDescribed.cases.push({description: description, fn: fn}); |
+} |
+ |
+before = function(fn) { |
+ context.beingDescribed.before = fn; |
+} |
+ |
+after = function(fn) { |
+ context.beingDescribed.after = fn; |
+} |
+ |
+beforeEach = function(fn) { |
+ context.beingDescribed.beforeEach = fn; |
+} |
+ |
+afterEach = function(fn) { |
+ context.beingDescribed.afterEach = fn; |
+} |
+ |
+}()); |