First commit

This commit is contained in:
2025-10-08 11:12:59 -04:00
commit b0605a28a9
820 changed files with 100317 additions and 0 deletions

104
node_modules/vasync/tests/compat.js generated vendored Normal file
View File

@ -0,0 +1,104 @@
/*
* tests/compat.js: Some of the APIs provided by vasync are intended to be
* API-compatible with node-async, so we incorporate the tests from node-async
* directly here. These are copied from https://github.com/caolan/async,
* available under the MIT license. To make it easy to update this from the
* source, this file should remain unchanged from the source except for this
* header comment, the change to the "require" line, and deleted lines for
* unimplemented functions.
*
* The following tests are deliberately omitted:
*
* o "waterfall non-array": Per Joyent's Best Practices for Node.js Error
* Handling, we're strict about argument types and throw on these programmer
* errors rather than emitting them asynchronously.
*
* o "waterfall multiple callback calls": We deliberately disallow a waterfall
* function to invoke its callback more than once, so we don't test for that
* here. The behavior that node-async allows can potentially be used to fork
* the waterfall, which may be useful, but it's often used instead as an
* excuse to write code sloppily. And the downside is that it makes it really
* hard to understand bugs where the waterfall was resumed too early. For
* now, we're disallowing it, but if the forking behavior becomes useful, we
* can always make our version less strict.
*/
var async = require('../lib/vasync');
exports['waterfall'] = function(test){
test.expect(6);
var call_order = [];
async.waterfall([
function(callback){
call_order.push('fn1');
setTimeout(function(){callback(null, 'one', 'two');}, 0);
},
function(arg1, arg2, callback){
call_order.push('fn2');
test.equals(arg1, 'one');
test.equals(arg2, 'two');
setTimeout(function(){callback(null, arg1, arg2, 'three');}, 25);
},
function(arg1, arg2, arg3, callback){
call_order.push('fn3');
test.equals(arg1, 'one');
test.equals(arg2, 'two');
test.equals(arg3, 'three');
callback(null, 'four');
},
function(arg4, callback){
call_order.push('fn4');
test.same(call_order, ['fn1','fn2','fn3','fn4']);
callback(null, 'test');
}
], function(err){
test.done();
});
};
exports['waterfall empty array'] = function(test){
async.waterfall([], function(err){
test.done();
});
};
exports['waterfall no callback'] = function(test){
async.waterfall([
function(callback){callback();},
function(callback){callback(); test.done();}
]);
};
exports['waterfall async'] = function(test){
var call_order = [];
async.waterfall([
function(callback){
call_order.push(1);
callback();
call_order.push(2);
},
function(callback){
call_order.push(3);
callback();
},
function(){
test.same(call_order, [1,2,3]);
test.done();
}
]);
};
exports['waterfall error'] = function(test){
test.expect(1);
async.waterfall([
function(callback){
callback('error');
},
function(callback){
test.ok(false, 'next function should not be called');
callback();
}
], function(err){
test.equals(err, 'error');
});
setTimeout(test.done, 50);
};

91
node_modules/vasync/tests/compat_tryEach.js generated vendored Normal file
View File

@ -0,0 +1,91 @@
var async = require('../lib/vasync');
/*
* tryEach tests, transliterated from mocha to tap.
*
* They are nearly identical except for some details related to vasync. For
* example, we don't support calling the callback more than once from any of
* the given functions.
*/
exports['tryEach no callback'] = function (test) {
async.tryEach([]);
test.done();
};
exports['tryEach empty'] = function (test) {
async.tryEach([], function (err, results) {
test.equals(err, null);
test.same(results, undefined);
test.done();
});
};
exports['tryEach one task, multiple results'] = function (test) {
var RESULTS = ['something', 'something2'];
async.tryEach([
function (callback) {
callback(null, RESULTS[0], RESULTS[1]);
}
], function (err, results) {
test.equals(err, null);
test.same(results, RESULTS);
test.done();
});
};
exports['tryEach one task'] = function (test) {
var RESULT = 'something';
async.tryEach([
function (callback) {
callback(null, RESULT);
}
], function (err, results) {
test.equals(err, null);
test.same(results, RESULT);
test.done();
});
};
exports['tryEach two tasks, one failing'] = function (test) {
var RESULT = 'something';
async.tryEach([
function (callback) {
callback(new Error('Failure'), {});
},
function (callback) {
callback(null, RESULT);
}
], function (err, results) {
test.equals(err, null);
test.same(results, RESULT);
test.done();
});
};
exports['tryEach two tasks, both failing'] = function (test) {
var ERROR_RESULT = new Error('Failure2');
async.tryEach([
function (callback) {
callback(new Error('Should not stop here'));
},
function (callback) {
callback(ERROR_RESULT);
}
], function (err, results) {
test.equals(err, ERROR_RESULT);
test.same(results, undefined);
test.done();
});
};
exports['tryEach two tasks, non failing'] = function (test) {
var RESULT = 'something';
async.tryEach([
function (callback) {
callback(null, RESULT);
},
function () {
test.fail('Should not been called');
}
], function (err, results) {
test.equals(err, null);
test.same(results, RESULT);
test.done();
});
};

226
node_modules/vasync/tests/filter.js generated vendored Normal file
View File

@ -0,0 +1,226 @@
/*
* Tests the "filter", "filterSeries", and "filterLimit" functions
*/
var mod_util = require('util');
var mod_tap = require('tap');
var mod_vasync = require('..');
mod_tap.test('filterSeries', function (test) {
var inputs = [0, 1, 2, 3, 4, 5];
var curTasks = 0;
var maxTasks = 0;
// filterSeries has an implicit limit of 1 concurrent operation
var limit = 1;
function filterFunc(input, cb) {
curTasks++;
if (curTasks > maxTasks) {
maxTasks = curTasks;
}
test.ok(curTasks <= limit, mod_util.format(
'input %d: current tasks %d <= %d',
input, curTasks, limit));
setTimeout(function () {
curTasks--;
cb(null, input < 2 || input === 4);
}, 50);
}
mod_vasync.filterSeries(inputs, filterFunc,
function filterDone(err, results) {
test.ok(!err, 'error unset');
test.equal(maxTasks, limit, 'max tasks reached limit');
test.deepEqual(results, [0, 1, 4], 'results array correct');
test.end();
});
});
mod_tap.test('filterLimit', function (test) {
var inputs = [0, 1, 2, 3, 4, 5];
var curTasks = 0;
var maxTasks = 0;
var limit = 2;
function filterFunc(input, cb) {
curTasks++;
if (curTasks > maxTasks) {
maxTasks = curTasks;
}
test.ok(curTasks <= limit, mod_util.format(
'input %d: current tasks %d <= %d',
input, curTasks, limit));
setTimeout(function () {
curTasks--;
cb(null, input < 2 || input === 4);
}, 50);
}
mod_vasync.filterLimit(inputs, limit, filterFunc,
function filterDone(err, results) {
test.ok(!err, 'error unset');
test.equal(maxTasks, limit, 'max tasks reached limit');
test.deepEqual(results, [0, 1, 4], 'results array correct');
test.end();
});
});
mod_tap.test('filter (maintain order)', function (test) {
var inputs = [0, 1, 2, 3, 4, 5];
var limit = inputs.length;
var storedValues = [];
function filterFunc(input, cb) {
/*
* Hold every callback in an array to be called when all
* filterFunc's have run. This way, we can ensure that all
* tasks have started without waiting for any others to finish.
*/
storedValues.push({
input: input,
cb: cb
});
test.ok(storedValues.length <= limit, mod_util.format(
'input %d: current tasks %d <= %d',
input, storedValues.length, limit));
/*
* When this constraint is true, all filterFunc's have run for
* each input. We now call all callbacks in a pre-determined
* order (out of order of the original) to ensure the final
* array is in the correct order.
*/
if (storedValues.length === inputs.length) {
[5, 2, 0, 1, 4, 3].forEach(function (i) {
var o = storedValues[i];
o.cb(null, o.input < 2 || o.input === 4);
});
}
}
mod_vasync.filter(inputs, filterFunc,
function filterDone(err, results) {
test.ok(!err, 'error unset');
test.equal(storedValues.length, inputs.length,
'max tasks reached limit');
test.deepEqual(results, [0, 1, 4], 'results array correct');
test.end();
});
});
mod_tap.test('filterSeries error handling', function (test) {
/*
* We will error half way through the list of inputs to ensure that
* first half are processed while the second half are ignored.
*/
var inputs = [0, 1, 2, 3, 4, 5];
function filterFunc(input, cb) {
switch (input) {
case 0:
case 1:
case 2:
cb(null, true);
break;
case 3:
cb(new Error('error on ' + input));
break;
case 4:
case 5:
test.ok(false, 'processed too many inputs');
cb(new Error('processed too many inputs'));
break;
default:
test.ok(false, 'unexpected input: ' + input);
cb(new Error('unexpected input'));
break;
}
}
mod_vasync.filterSeries(inputs, filterFunc,
function filterDone(err, results) {
test.ok(err, 'error set');
test.ok(err.message === 'error on 3', 'error on input 3');
test.ok(results === undefined, 'results is unset');
test.end();
});
});
mod_tap.test('filterSeries double callback', function (test) {
var inputs = [0, 1, 2, 3, 4, 5];
function filterFunc(input, cb) {
switch (input) {
case 0:
case 1:
case 2:
cb(null, true);
break;
case 3:
/*
* The first call to cb() should "win" - meaning this
* value will be filtered out of the final array of
* results.
*/
cb(null, false);
test.throws(function () {
cb(null, true);
});
break;
case 4:
/*
* Like input 3, all subsequent calls to cb() will
* throw an error and not affect the original call to
* cb().
*/
cb(null, true);
test.throws(function () {
cb(new Error('uh oh'));
});
break;
case 5:
cb(null, true);
break;
default:
test.ok(false, 'unexpected input: ' + input);
cb(new Error('unexpected input'));
break;
}
}
mod_vasync.filterSeries(inputs, filterFunc,
function filterDone(err, results) {
test.ok(!err, 'error not set');
test.deepEqual(results, [0, 1, 2, 4, 5],
'results array correct');
test.end();
});
});
mod_tap.test('filter push to queue object error', function (test) {
var inputs = [0, 1, 2, 3, 4, 5];
function filterFunc(input, cb) {
cb(null, true);
}
var q = mod_vasync.filterSeries(inputs, filterFunc,
function filterDone(err, results) {
test.end();
});
test.equal(q.closed, true, 'queue is closed');
test.throws(function () {
q.push(6);
});
});

25
node_modules/vasync/tests/issue-21.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
/*
* Tests that if the user modifies the list of functions passed to
* vasync.pipeline, vasync ignores the changes and does not crash.
*/
var assert = require('assert');
var vasync = require('../lib/vasync');
var count = 0;
var funcs;
function doStuff(_, callback)
{
count++;
setImmediate(callback);
}
funcs = [ doStuff, doStuff, doStuff ];
vasync.pipeline({
'funcs': funcs
}, function (err) {
assert.ok(!err);
assert.ok(count === 3);
});
funcs.push(doStuff);

132
node_modules/vasync/tests/pipeline.js generated vendored Normal file
View File

@ -0,0 +1,132 @@
/*
* Tests the "pipeline" primitive.
*/
var mod_tap = require('tap');
var mod_vasync = require('..');
var st;
mod_tap.test('empty pipeline', function (test) {
var count = 0;
st = mod_vasync.pipeline({'funcs': [], 'arg': null},
function (err, result) {
test.ok(err === null);
test.ok(result.ndone === 0);
test.ok(result.nerrors === 0);
test.ok(result.operations.length === 0);
test.ok(result.successes.length === 0);
test.equal(count, 1);
test.end();
});
count++;
test.ok(st.ndone === 0);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 0);
test.ok(st.successes.length === 0);
});
mod_tap.test('normal 4-stage pipeline', function (test) {
var count = 0;
st = mod_vasync.pipeline({'funcs': [
function func1(_, cb) {
test.equal(st.successes[0], undefined,
'func1: successes');
test.ok(count === 0, 'func1: count === 0');
test.ok(st.ndone === 0);
count++;
setImmediate(cb, null, count);
},
function func2(_, cb) {
test.equal(st.successes[0], 1, 'func2: successes');
test.ok(count == 1, 'func2: count == 1');
test.ok(st.ndone === 1);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'pending');
test.ok(st.operations[2].status == 'waiting');
count++;
setImmediate(cb, null, count);
},
function (_, cb) {
test.equal(st.successes[0], 1, 'func3: successes');
test.equal(st.successes[1], 2, 'func3: successes');
test.ok(count == 2, 'func3: count == 2');
test.ok(st.ndone === 2);
count++;
setImmediate(cb, null, count);
},
function func4(_, cb) {
test.equal(st.successes[0], 1, 'func4: successes');
test.equal(st.successes[1], 2, 'func4: successes');
test.equal(st.successes[2], 3, 'func4: successes');
test.ok(count == 3, 'func4: count == 3');
test.ok(st.ndone === 3);
count++;
setImmediate(cb, null, count);
}
]}, function (err, result) {
test.ok(count == 4, 'final: count == 4');
test.ok(err === null, 'no error');
test.ok(result === st);
test.equal(result, st, 'final-cb: st == result');
test.equal(st.successes[0], 1, 'final-cb: successes');
test.equal(st.successes[1], 2, 'final-cb: successes');
test.equal(st.successes[2], 3, 'final-cb: successes');
test.equal(st.successes[3], 4, 'final-cb: successes');
test.ok(st.ndone === 4);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 4);
test.ok(st.successes.length === 4);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'ok');
test.ok(st.operations[2].status == 'ok');
test.ok(st.operations[3].status == 'ok');
test.end();
});
test.ok(st.ndone === 0);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 4);
test.ok(st.operations[0].funcname == 'func1', 'func1 name');
test.ok(st.operations[0].status == 'pending');
test.ok(st.operations[1].funcname == 'func2', 'func2 name');
test.ok(st.operations[1].status == 'waiting');
test.ok(st.operations[2].funcname == '(anon)', 'anon name');
test.ok(st.operations[2].status == 'waiting');
test.ok(st.operations[3].funcname == 'func4', 'func4 name');
test.ok(st.operations[3].status == 'waiting');
test.ok(st.successes.length === 0);
});
mod_tap.test('bailing out early', function (test) {
var count = 0;
st = mod_vasync.pipeline({'funcs': [
function func1(_, cb) {
test.ok(count === 0, 'func1: count === 0');
count++;
setImmediate(cb, null, count);
},
function func2(_, cb) {
test.ok(count == 1, 'func2: count == 1');
count++;
setImmediate(cb, new Error('boom!'));
},
function func3(_, cb) {
test.ok(count == 2, 'func3: count == 2');
count++;
setImmediate(cb, null, count);
}
]}, function (err, result) {
test.ok(count == 2, 'final: count == 3');
test.equal(err.message, 'boom!');
test.ok(result === st);
test.equal(result, st, 'final-cb: st == result');
test.ok(st.ndone == 2);
test.ok(st.nerrors == 1);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'fail');
test.ok(st.operations[2].status == 'waiting');
test.ok(st.successes.length == 1);
test.end();
});
});

284
node_modules/vasync/tests/queue.js generated vendored Normal file
View File

@ -0,0 +1,284 @@
/* vim: set ts=8 sts=8 sw=8 noet: */
var mod_tap = require('tap');
var mod_vasync = require('..');
function
immediate_worker(task, next)
{
setImmediate(function () {
next();
});
}
function
sametick_worker(task, next)
{
next();
}
function
random_delay_worker(task, next)
{
setTimeout(function () {
next();
}, Math.floor(Math.random() * 250));
}
mod_tap.test('must not push after close', function (test) {
test.plan(3);
var q = mod_vasync.queuev({
worker: immediate_worker,
concurrency: 10
});
test.ok(q);
test.doesNotThrow(function () {
q.push({});
}, 'push should not throw _before_ close()');
q.close();
/*
* If we attempt to add tasks to the queue _after_ calling close(),
* we should get an exception:
*/
test.throws(function () {
q.push({});
}, 'push should throw _after_ close()');
test.end();
});
mod_tap.test('get \'end\' event with close()', function (test) {
var task_count = 45;
var tasks_finished = 0;
var seen_end = false;
var seen_drain = false;
test.plan(14 + task_count);
var q = mod_vasync.queuev({
worker: random_delay_worker,
concurrency: 5
});
test.ok(q);
/*
* Enqueue a bunch of tasks; more than our concurrency:
*/
for (var i = 0; i < 45; i++) {
q.push({}, function () {
tasks_finished++;
test.ok(true);
});
}
/*
* Close the queue to signify that we're done now.
*/
test.equal(q.ended, false);
test.equal(q.closed, false);
q.close();
test.equal(q.closed, true);
test.equal(q.ended, false);
q.on('drain', function () {
/*
* 'drain' should fire before 'end':
*/
test.notOk(seen_drain);
test.notOk(seen_end);
seen_drain = true;
});
q.on('end', function () {
/*
* 'end' should fire after 'drain':
*/
test.ok(seen_drain);
test.notOk(seen_end);
seen_end = true;
/*
* Check the public state:
*/
test.equal(q.closed, true);
test.equal(q.ended, true);
/*
* We should have fired the callbacks for _all_ enqueued
* tasks by now:
*/
test.equal(task_count, tasks_finished);
test.end();
});
/*
* Check that we see neither the 'drain', nor the 'end' event before
* the end of this tick:
*/
test.notOk(seen_drain);
test.notOk(seen_end);
});
mod_tap.test('get \'end\' event with close() and no tasks', function (test) {
var seen_drain = false;
var seen_end = false;
test.plan(10);
var q = mod_vasync.queuev({
worker: immediate_worker,
concurrency: 10
});
setImmediate(function () {
test.notOk(seen_end);
});
test.equal(q.ended, false);
test.equal(q.closed, false);
q.close();
test.equal(q.closed, true);
test.equal(q.ended, false);
test.notOk(seen_end);
q.on('drain', function () {
seen_drain = true;
});
q.on('end', function () {
/*
* We do not expect to see a 'drain' event, as there were no
* tasks pushed onto the queue before we closed it.
*/
test.notOk(seen_drain);
test.notOk(seen_end);
test.equal(q.closed, true);
test.equal(q.ended, true);
seen_end = true;
test.end();
});
});
/*
* We want to ensure that both the 'drain' event and the q.drain() hook are
* called the same number of times:
*/
mod_tap.test('equivalence of on(\'drain\') and q.drain()', function (test) {
var enqcount = 4;
var drains = 4;
var ee_count = 0;
var fn_count = 0;
test.plan(enqcount + drains + 3);
var q = mod_vasync.queuev({
worker: immediate_worker,
concurrency: 10
});
var enq = function () {
if (--enqcount < 0)
return;
q.push({}, function () {
test.ok(true, 'task completion');
});
};
var draino = function () {
test.ok(true, 'drain called');
if (--drains === 0) {
test.equal(q.closed, false, 'not closed');
test.equal(q.ended, false, 'not ended');
test.equal(fn_count, ee_count, 'same number of calls');
test.end();
}
};
enq();
enq();
q.on('drain', function () {
ee_count++;
enq();
draino();
});
q.drain = function () {
fn_count++;
enq();
draino();
};
});
/*
* In the past, we've only handed on the _first_ argument to the task completion
* callback. Make sure we hand on _all_ of the arguments now:
*/
mod_tap.test('ensure all arguments passed to push() callback', function (test) {
test.plan(13);
var q = mod_vasync.queuev({
worker: function (task, callback) {
if (task.fail) {
callback(new Error('guru meditation'));
return;
}
callback(null, 1, 2, 3, 5, 8);
},
concurrency: 1
});
q.push({ fail: true }, function (err, a, b, c, d, e) {
test.ok(err, 'got the error');
test.equal(err.message, 'guru meditation');
test.type(a, 'undefined');
test.type(b, 'undefined');
test.type(c, 'undefined');
test.type(d, 'undefined');
test.type(e, 'undefined');
});
q.push({ fail: false }, function (err, a, b, c, d, e) {
test.notOk(err, 'got no error');
test.equal(a, 1);
test.equal(b, 2);
test.equal(c, 3);
test.equal(d, 5);
test.equal(e, 8);
});
q.drain = function () {
test.end();
};
});
mod_tap.test('queue kill', function (test) {
// Derived from async queue.kill test
var count = 0;
var q = mod_vasync.queuev({
worker: function (task, callback) {
setImmediate(function () {
test.ok(++count < 2,
'Function should be called once');
callback();
});
},
concurrency: 1
});
q.drain = function () {
test.ok(false, 'Function should never be called');
};
// Queue twice, the first will exec immediately
q.push(0);
q.push(0);
q.kill();
q.on('end', function () {
test.ok(q.killed);
test.end();
});
});

181
node_modules/vasync/tests/queue_concurrency.js generated vendored Normal file
View File

@ -0,0 +1,181 @@
/* vim: set ts=8 sts=8 sw=8 noet: */
var mod_tap = require('tap');
var mod_vasync = require('..');
function
latched_worker(task, cb)
{
if (task.immediate) {
cb();
} else {
task.latched = true;
task.unlatch = function () {
task.latched = false;
cb();
};
}
}
function
unlatchAll(tasks)
{
tasks.forEach(function (t) {
if (t.latched) {
t.unlatch();
}
});
}
function
setAllImmediate(tasks)
{
tasks.forEach(function (t) {
t.immediate = true;
});
}
mod_tap.test('test serial tasks', function (test) {
test.plan(2);
var q = mod_vasync.queuev({
worker: latched_worker,
concurrency: 1
});
test.ok(q);
var tasks = [];
for (var i = 0; i < 2; ++i) {
tasks.push({
'id': i,
'latched': false,
'immediate': false
});
}
setTimeout(function () {
var latched = 0;
tasks.forEach(function (t) {
if (t.latched) {
++latched;
}
});
test.ok(latched === 1);
unlatchAll(tasks);
setAllImmediate(tasks);
}, 10);
q.on('drain', function () {
q.close();
});
q.on('end', function () {
test.end();
});
q.push(tasks);
});
mod_tap.test('test parallel tasks', function (test) {
test.plan(2);
var q = mod_vasync.queuev({
worker: latched_worker,
concurrency: 2
});
test.ok(q);
var tasks = [];
for (var i = 0; i < 3; ++i) {
tasks.push({
'id': i,
'latched': false,
'immediate': false
});
}
setTimeout(function () {
var latched = 0;
tasks.forEach(function (t) {
if (t.latched) {
++latched;
}
});
test.ok(latched === 2);
unlatchAll(tasks);
setAllImmediate(tasks);
}, 10);
q.on('drain', function () {
q.close();
});
q.on('end', function () {
test.end();
});
q.push(tasks);
});
mod_tap.test('test ratchet up and down', function (test) {
test.plan(8);
var q = mod_vasync.queuev({
worker: latched_worker,
concurrency: 2
});
test.ok(q);
var bounced = 0;
var tasks = [];
for (var i = 0; i < 21; ++i) {
tasks.push({
'id': i,
'latched': false,
'immediate': false
});
}
function count() {
var latched = 0;
tasks.forEach(function (t) {
if (t.latched) {
++latched;
}
});
return (latched);
}
function fiveLatch() {
if (!q.closed) {
++bounced;
test.ok(count() === 5);
q.updateConcurrency(2);
unlatchAll(tasks);
setTimeout(twoLatch, 10);
}
}
function twoLatch() {
if (!q.closed) {
++bounced;
test.ok(count() === 2);
q.updateConcurrency(5);
unlatchAll(tasks);
setTimeout(fiveLatch, 10);
}
}
setTimeout(twoLatch, 10);
q.on('drain', function () {
q.close();
});
q.on('end', function () {
// 21 tasks === 5 * 3 + 2 * 3 === 6 bounces
test.ok(bounced === 6);
test.end();
});
q.push(tasks);
});

179
node_modules/vasync/tests/waterfall.js generated vendored Normal file
View File

@ -0,0 +1,179 @@
/*
* Tests the "waterfall" primitive.
*/
var mod_tap = require('tap');
var mod_vasync = require('..');
var count = 0;
var st;
mod_tap.test('empty waterfall', function (test) {
st = mod_vasync.waterfall([], function (err) {
test.ok(err === null);
test.ok(st.ndone === 0);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 0);
test.ok(st.successes.length === 0);
test.equal(count, 1);
test.end();
});
count++;
test.ok(st.ndone === 0);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 0);
test.ok(st.successes.length === 0);
});
mod_tap.test('normal 4-stage waterfall', function (test) {
count = 0;
st = mod_vasync.waterfall([
function func1(cb) {
test.ok(count === 0, 'func1: count === 0');
test.ok(st.ndone === 0);
count++;
setTimeout(cb, 20, null, { 'hello': 'world' });
},
function func2(extra, cb) {
test.equal(extra.hello, 'world', 'func2: extra arg');
test.ok(count == 1, 'func2: count == 1');
test.ok(st.ndone === 1);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'pending');
test.ok(st.operations[2].status == 'waiting');
count++;
setTimeout(cb, 20, null, 5, 6, 7);
},
function (five, six, seven, cb) {
test.equal(five, 5, 'func3: extra arg');
test.equal(six, 6, 'func3: extra arg');
test.equal(seven, 7, 'func3: extra arg');
test.ok(count == 2, 'func3: count == 2');
test.ok(st.ndone === 2);
count++;
setTimeout(cb, 20);
},
function func4(cb) {
test.ok(count == 3, 'func4: count == 2');
test.ok(st.ndone === 3);
count++;
setTimeout(cb, 20, null, 8, 9);
}
], function (err, eight, nine) {
test.ok(count == 4, 'final: count == 4');
test.ok(err === null, 'no error');
test.ok(eight == 8);
test.ok(nine == 9);
test.ok(st.ndone === 4);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 4);
test.ok(st.successes.length === 4);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'ok');
test.ok(st.operations[2].status == 'ok');
test.ok(st.operations[3].status == 'ok');
test.end();
});
test.ok(st.ndone === 0);
test.ok(st.nerrors === 0);
test.ok(st.operations.length === 4);
test.ok(st.operations[0].funcname == 'func1', 'func1 name');
test.ok(st.operations[0].status == 'pending');
test.ok(st.operations[1].funcname == 'func2', 'func2 name');
test.ok(st.operations[1].status == 'waiting');
test.ok(st.operations[2].funcname == '(anon)', 'anon name');
test.ok(st.operations[2].status == 'waiting');
test.ok(st.operations[3].funcname == 'func4', 'func4 name');
test.ok(st.operations[3].status == 'waiting');
test.ok(st.successes.length === 0);
});
mod_tap.test('bailing out early', function (test) {
count = 0;
st = mod_vasync.waterfall([
function func1(cb) {
test.ok(count === 0, 'func1: count === 0');
count++;
setTimeout(cb, 20);
},
function func2(cb) {
test.ok(count == 1, 'func2: count == 1');
count++;
setTimeout(cb, 20, new Error('boom!'));
},
function func3(cb) {
test.ok(count == 2, 'func3: count == 2');
count++;
setTimeout(cb, 20);
}
], function (err) {
test.ok(count == 2, 'final: count == 3');
test.equal(err.message, 'boom!');
test.ok(st.ndone == 2);
test.ok(st.nerrors == 1);
test.ok(st.operations[0].status == 'ok');
test.ok(st.operations[1].status == 'fail');
test.ok(st.operations[2].status == 'waiting');
test.ok(st.successes.length == 1);
test.end();
});
});
mod_tap.test('bad function', function (test) {
count = 0;
st = mod_vasync.waterfall([
function func1(cb) {
count++;
cb();
setTimeout(function () {
test.throws(
function () { cb(); process.abort(); },
'vasync.waterfall: ' +
'function 0 ("func1") invoked its ' +
'callback twice');
test.equal(count, 2);
test.end();
}, 100);
},
function func2(cb) {
count++;
/* do nothing -- we'll throw an exception first */
}
], function (err) {
/* not reached */
console.error('didn\'t expect to finish');
process.abort();
});
});
mod_tap.test('badargs', function (test) {
test.throws(function () { mod_vasync.waterfall(); });
test.throws(function () { mod_vasync.waterfall([], 'foo'); });
test.throws(function () { mod_vasync.waterfall('foo', 'bar'); });
test.end();
});
mod_tap.test('normal waterfall, no callback', function (test) {
count = 0;
st = mod_vasync.waterfall([
function func1(cb) {
test.ok(count === 0);
count++;
setImmediate(cb);
},
function func2(cb) {
test.ok(count == 1);
count++;
setImmediate(cb);
setTimeout(function () {
test.ok(count == 2);
test.end();
}, 100);
}
]);
});
mod_tap.test('empty waterfall, no callback', function (test) {
st = mod_vasync.waterfall([]);
setTimeout(function () { test.end(); }, 100);
});

108
node_modules/vasync/tests/whilst.js generated vendored Normal file
View File

@ -0,0 +1,108 @@
/*
* Tests the "whilst" function
*/
var mod_util = require('util');
var mod_tap = require('tap');
var mod_vasync = require('..');
mod_tap.test('basic whilst', function (test) {
var n = 0;
mod_vasync.whilst(
function condition() {
return (n < 5);
},
function body(cb) {
n++;
cb(null, n);
},
function done(err, arg) {
test.ok(!err, 'error unset');
test.equal(n, 5, 'n == 5');
test.equal(n, arg, 'n == arg');
test.end();
});
});
mod_tap.test('whilst return object', function (test) {
var n = 0;
var w = mod_vasync.whilst(
function condition() {
return (n < 5);
},
function body(cb) {
n++;
test.equal(n, w.iterations, 'n == w.iterations: ' + n);
cb(null, n, 'foo');
},
function done(err, arg1, arg2, arg3) {
test.ok(!err, 'error unset');
test.equal(w.iterations, 5, 'whilst had 5 iterations');
test.equal(w.finished, true, 'whilst has finished');
test.equal(arg1, n, 'whilst arg1 == n');
test.equal(arg2, 'foo', 'whilst arg2 == "foo"');
test.equal(arg3, undefined, 'whilst arg3 == undefined');
test.end();
});
test.equal(typeof (w), 'object', 'whilst returns an object');
test.equal(w.finished, false, 'whilst is not finished');
test.equal(w.iterations, 0, 'whilst has not started yet');
});
mod_tap.test('whilst false condition', function (test) {
mod_vasync.whilst(
function condition() {
return (false);
},
function body(cb) {
cb();
},
function done(err, arg) {
test.ok(!err, 'error is unset');
test.ok(!arg, 'arg is unset');
test.end();
});
});
mod_tap.test('whilst error', function (test) {
var n = 0;
var w = mod_vasync.whilst(
function condition() {
return (true);
},
function body(cb) {
n++;
if (n > 5) {
cb(new Error('n > 5'), 'bar');
} else {
cb(null, 'foo');
}
},
function done(err, arg) {
test.ok(err, 'error is set');
test.equal(err.message, 'n > 5');
test.equal(arg, 'bar');
test.equal(w.finished, true, 'whilst is finished');
/*
* Iterations is bumped after the test condition is run and
* before the iteration function is run. Because the condition
* in this example is inside the iteration function (the test
* condition always returns true), the iteration count will be
* 1 higher than expected, since it will fail when (n > 5), or
* when iterations is 6.
*/
test.equal(w.iterations, 6, 'whilst had 6 iterations');
test.end();
});
});