[6a3a178] | 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 | }
|
---|