| [9af201e] | 1 | // Copyright Joyent, Inc. and other Node contributors.
|
|---|
| 2 | //
|
|---|
| 3 | // Permission is hereby granted, free of charge, to any person obtaining a
|
|---|
| 4 | // copy of this software and associated documentation files (the
|
|---|
| 5 | // "Software"), to deal in the Software without restriction, including
|
|---|
| 6 | // without limitation the rights to use, copy, modify, merge, publish,
|
|---|
| 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit
|
|---|
| 8 | // persons to whom the Software is furnished to do so, subject to the
|
|---|
| 9 | // following conditions:
|
|---|
| 10 | //
|
|---|
| 11 | // The above copyright notice and this permission notice shall be included
|
|---|
| 12 | // in all copies or substantial portions of the Software.
|
|---|
| 13 | //
|
|---|
| 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|---|
| 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|---|
| 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|---|
| 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|---|
| 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|---|
| 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|---|
| 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|---|
| 21 |
|
|---|
| 22 | var test = require('tape');
|
|---|
| 23 | var assert = require('assert');
|
|---|
| 24 |
|
|---|
| 25 | var noop = function() {};
|
|---|
| 26 |
|
|---|
| 27 | var mustCallChecks = [];
|
|---|
| 28 |
|
|---|
| 29 | function runCallChecks(exitCode) {
|
|---|
| 30 | if (exitCode !== 0) return;
|
|---|
| 31 |
|
|---|
| 32 | var failed = filter(mustCallChecks, function(context) {
|
|---|
| 33 | if ('minimum' in context) {
|
|---|
| 34 | context.messageSegment = 'at least ' + context.minimum;
|
|---|
| 35 | return context.actual < context.minimum;
|
|---|
| 36 | } else {
|
|---|
| 37 | context.messageSegment = 'exactly ' + context.exact;
|
|---|
| 38 | return context.actual !== context.exact;
|
|---|
| 39 | }
|
|---|
| 40 | });
|
|---|
| 41 |
|
|---|
| 42 | for (var i = 0; i < failed.length; i++) {
|
|---|
| 43 | var context = failed[i];
|
|---|
| 44 | console.log('Mismatched %s function calls. Expected %s, actual %d.',
|
|---|
| 45 | context.name,
|
|---|
| 46 | context.messageSegment,
|
|---|
| 47 | context.actual);
|
|---|
| 48 | // IE8 has no .stack
|
|---|
| 49 | if (context.stack) console.log(context.stack.split('\n').slice(2).join('\n'));
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | assert.strictEqual(failed.length, 0);
|
|---|
| 53 | }
|
|---|
| 54 |
|
|---|
| 55 | exports.mustCall = function(fn, exact) {
|
|---|
| 56 | return _mustCallInner(fn, exact, 'exact');
|
|---|
| 57 | };
|
|---|
| 58 |
|
|---|
| 59 | function _mustCallInner(fn, criteria, field) {
|
|---|
| 60 | if (typeof criteria == 'undefined') criteria = 1;
|
|---|
| 61 |
|
|---|
| 62 | if (typeof fn === 'number') {
|
|---|
| 63 | criteria = fn;
|
|---|
| 64 | fn = noop;
|
|---|
| 65 | } else if (fn === undefined) {
|
|---|
| 66 | fn = noop;
|
|---|
| 67 | }
|
|---|
| 68 |
|
|---|
| 69 | if (typeof criteria !== 'number')
|
|---|
| 70 | throw new TypeError('Invalid ' + field + ' value: ' + criteria);
|
|---|
| 71 |
|
|---|
| 72 | var context = {
|
|---|
| 73 | actual: 0,
|
|---|
| 74 | stack: (new Error()).stack,
|
|---|
| 75 | name: fn.name || '<anonymous>'
|
|---|
| 76 | };
|
|---|
| 77 |
|
|---|
| 78 | context[field] = criteria;
|
|---|
| 79 |
|
|---|
| 80 | // add the exit listener only once to avoid listener leak warnings
|
|---|
| 81 | if (mustCallChecks.length === 0) test.onFinish(function() { runCallChecks(0); });
|
|---|
| 82 |
|
|---|
| 83 | mustCallChecks.push(context);
|
|---|
| 84 |
|
|---|
| 85 | return function() {
|
|---|
| 86 | context.actual++;
|
|---|
| 87 | return fn.apply(this, arguments);
|
|---|
| 88 | };
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | exports.mustNotCall = function(msg) {
|
|---|
| 92 | return function mustNotCall() {
|
|---|
| 93 | assert.fail(msg || 'function should not have been called');
|
|---|
| 94 | };
|
|---|
| 95 | };
|
|---|
| 96 |
|
|---|
| 97 | function filter(arr, fn) {
|
|---|
| 98 | if (arr.filter) return arr.filter(fn);
|
|---|
| 99 | var filtered = [];
|
|---|
| 100 | for (var i = 0; i < arr.length; i++) {
|
|---|
| 101 | if (fn(arr[i], i, arr)) filtered.push(arr[i]);
|
|---|
| 102 | }
|
|---|
| 103 | return filtered
|
|---|
| 104 | }
|
|---|