forkjoin
Version:
Fork/Join primitives for async programming (experimental)
396 lines (372 loc) • 10.5 kB
JavaScript
// Generated by CoffeeScript 1.9.1
(function() {
var fj, isFunction, test;
test = require('tape');
fj = require('./forkjoin.js');
isFunction = function(f) {
return 'function' === typeof f;
};
test('async', function(t) {
var add;
t.plan(2);
add = fj.async(function(a, b) {
return a + b;
});
t.ok(isFunction(add));
return add(36, 6, function(error, result) {
return t.equal(42, result);
});
});
test('async - failure', function(t) {
var add;
t.plan(1);
add = fj.async(function(a, b) {
throw new Error('meh');
});
return add(36, 6, function(error, result) {
return t.equal(error.message, 'meh');
});
});
test('isFuture', function(t) {
var add, sum;
t.plan(7);
t.notOk(fj.isFuture(void 0));
t.notOk(fj.isFuture(null));
t.notOk(fj.isFuture({}));
t.notOk(fj.isFuture(42));
t.notOk(fj.isFuture('foo'));
t.notOk(fj.isFuture(new Date()));
add = fj.task(function(a, b, go) {
return go(null, a + b);
});
sum = add(36, 6);
return t.ok(fj.isFuture(sum));
});
test('resolve', function(t) {
var add, sum;
t.plan(4);
add = fj.task(function(a, b, go) {
return go(null, a + b);
});
sum = add(36, 6);
fj.resolve(sum, function(error, answer) {
t.equal(error, null);
return t.equal(answer, 42);
});
return fj.resolve(42, function(error, answer) {
t.equal(error, null);
return t.equal(answer, 42);
});
});
test('fork non-function', function(t) {
t.plan(1);
return t.throws(function() {
return fj.fork(void 0);
});
});
test('task non-function', function(t) {
t.plan(1);
return t.throws(function() {
return fj.task(void 0);
});
});
test('task - fulfilled', function(t) {
var add, sum;
t.plan(26);
add = fj.task(function(a, b, go) {
return go(null, a + b);
});
sum = add(36, 6);
t.ok(isFunction(sum.method));
t.deepEqual(sum.args, [36, 6]);
t.ok(sum.error === void 0);
t.ok(sum.result === void 0);
t.equal(sum.isFuture, true);
t.equal(sum.fulfilled, false);
t.equal(sum.rejected, false);
t.equal(sum.settled, false);
t.equal(sum.pending, true);
sum(function(error, result) {
t.equal(error, null);
return t.equal(42, result);
});
t.ok(sum.error === void 0);
t.ok(sum.result === 42);
t.equal(sum.fulfilled, true);
t.equal(sum.rejected, false);
t.equal(sum.settled, true);
t.equal(sum.pending, false);
sum(function(error, result) {
t.equal(error, null);
return t.equal(42, result);
});
t.ok(sum.error === void 0);
t.ok(sum.error === void 0);
t.ok(sum.result === 42);
t.equal(sum.fulfilled, true);
t.equal(sum.rejected, false);
t.equal(sum.settled, true);
return t.equal(sum.pending, false);
});
test('task - rejected', function(t) {
var add, sum;
t.plan(25);
add = fj.task(function(a, b, go) {
return go(new Error('meh'));
});
sum = add(36, 6);
t.ok(isFunction(sum.method));
t.deepEqual(sum.args, [36, 6]);
t.ok(sum.error === void 0);
t.ok(sum.result === void 0);
t.equal(sum.isFuture, true);
t.equal(sum.fulfilled, false);
t.equal(sum.rejected, false);
t.equal(sum.settled, false);
t.equal(sum.pending, true);
sum(function(error, result) {
t.equal(error.message, 'meh');
return t.ok(result === void 0);
});
t.ok(sum.error.message, 'meh');
t.ok(sum.result === void 0);
t.equal(sum.fulfilled, false);
t.equal(sum.rejected, true);
t.equal(sum.settled, true);
t.equal(sum.pending, false);
sum(function(error, result) {
t.equal(error.message, 'meh');
return t.ok(result === void 0);
});
t.ok(sum.error.message, 'meh');
t.ok(sum.result === void 0);
t.equal(sum.fulfilled, false);
t.equal(sum.rejected, true);
t.equal(sum.settled, true);
return t.equal(sum.pending, false);
});
test('join - empty', function(t) {
t.plan(2);
return fj.join([], function(error, result) {
t.equal(error, null);
return t.deepEqual(result, []);
});
});
test('join - future of futures', function(t) {
var pow16, pow4, square, twoPow16;
t.plan(2);
square = fj.task(fj.async(function(a) {
return a * a;
}));
pow4 = fj.task(fj.async(function(a) {
return square(square(a));
}));
pow16 = fj.task(fj.async(function(a) {
return pow4(pow4(a));
}));
twoPow16 = pow16(2);
return twoPow16(function(error, result) {
t.equal(error, null);
return t.equal(result, Math.pow(2, 16));
});
});
test('task - futures', function(t) {
var bar, concat, foo, foobar, uppercase;
t.plan(2);
uppercase = fj.task(function(a, go) {
return go(null, a.toUpperCase());
});
concat = fj.task(function(a, b, go) {
return go(null, a + b);
});
foo = uppercase('foo');
bar = uppercase('bar');
foobar = concat(foo, bar);
return foobar(function(error, result) {
t.equal(error, null);
return t.equal(result, 'FOOBAR');
});
});
test('task - failing futures', function(t) {
var bar, concat, foo, foobar, uppercase;
t.plan(1);
uppercase = fj.task(function(a, go) {
return go(new Error('meh'));
});
concat = fj.task(function(a, b, go) {
return go(null, a + b);
});
foo = uppercase('foo');
bar = uppercase('bar');
foobar = concat(foo, bar);
return foobar(function(error, result) {
return t.equal(error.message, 'meh');
});
});
test('seq', function(t) {
var i, lengthOf, wordAt, wordLengths, words;
t.plan(2);
words = ['qux', 'quux', 'quuux'];
lengthOf = fj.task(function(a, go) {
return go(null, a.length);
});
wordAt = fj.task(function(i, go) {
return go(null, words[i]);
});
wordLengths = fj.seq((function() {
var j, results;
results = [];
for (i = j = 0; j < 3; i = ++j) {
results.push(lengthOf(wordAt(i)));
}
return results;
})());
return wordLengths(function(error, wordLengths) {
t.equal(error, null);
return t.deepEqual(wordLengths, [3, 4, 5]);
});
});
test('collect', function(t) {
var i, lengthOf, wordAt, wordLengths, words;
t.plan(2);
words = ['qux', 'quux', 'quuux'];
lengthOf = fj.task(function(a, go) {
return go(null, a.length);
});
wordAt = fj.task(function(i, go) {
return go(null, words[i]);
});
wordLengths = fj.collect((function() {
var j, results;
results = [];
for (i = j = 0; j < 3; i = ++j) {
results.push(lengthOf(wordAt(i)));
}
return results;
})());
return wordLengths(function(error, wordLengths) {
t.equal(error, null);
return t.deepEqual(wordLengths, [3, 4, 5]);
});
});
test('seq - failing futures', function(t) {
var i, lengthOf, wordAt, wordLengths, words;
t.plan(1);
words = ['qux', 'quux', 'quuux'];
lengthOf = fj.task(function(a, go) {
return go(null, a.length);
});
wordAt = fj.task(function(i, go) {
return go(new Error('meh'));
});
wordLengths = fj.seq((function() {
var j, results;
results = [];
for (i = j = 0; j < 3; i = ++j) {
results.push(lengthOf(wordAt(i)));
}
return results;
})());
return wordLengths(function(error, wordLengths) {
return t.equal(error.message, 'meh');
});
});
test('collect - failing futures', function(t) {
var i, lengthOf, wordAt, wordLengths, words;
t.plan(1);
words = ['qux', 'quux', 'quuux'];
lengthOf = fj.task(function(a, go) {
return go(null, a.length);
});
wordAt = fj.task(function(i, go) {
return go(new Error('meh'));
});
wordLengths = fj.collect((function() {
var j, results;
results = [];
for (i = j = 0; j < 3; i = ++j) {
results.push(lengthOf(wordAt(i)));
}
return results;
})());
return wordLengths(function(error, wordLengths) {
return t.equal(error.message, 'meh');
});
});
test('lift', function(t) {
var bar, baz, echo, foo, joined;
t.plan(2);
echo = fj.task(fj.async(function(a) {
return a;
}));
foo = echo('foo');
bar = echo('bar');
baz = echo('baz');
joined = fj.lift(foo, bar, baz, function(foo, bar, baz) {
return foo + bar + baz;
});
return joined(function(error, result) {
t.equal(error, null);
return t.equal(result, 'foobarbaz');
});
});
test('math example', function(t) {
var answer, square, times10, twice;
t.plan(2);
twice = fj.task(fj.async(function(a) {
return a * 2;
}));
square = fj.task(fj.async(function(a) {
return a * a;
}));
times10 = fj.task(fj.async(function(a) {
return a * 10;
}));
answer = times10(square(twice(4)));
return answer(function(error, result) {
t.equal(error, null);
return t.equal(result, 640);
});
});
test('wordcount example', function(t) {
var allCounts, combineCounts, countWords, sentences, tokenize;
t.plan(1);
tokenize = fj.task(fj.async(function(sentence) {
return sentence.split(/\s+/g);
}));
countWords = fj.task(fj.async(function(words) {
var countMap, j, len, word;
countMap = {};
for (j = 0, len = words.length; j < len; j++) {
word = words[j];
countMap[word] = word in countMap ? countMap[word] + 1 : 1;
}
return countMap;
}));
combineCounts = fj.task(fj.async(function(countMaps) {
var count, countMap, counts, j, len, word;
counts = {};
for (j = 0, len = countMaps.length; j < len; j++) {
countMap = countMaps[j];
for (word in countMap) {
count = countMap[word];
counts[word] = word in counts ? counts[word] + count : count;
}
}
return counts;
}));
sentences = ['hello world bye world', 'hello forkjoin goodbye forkjoin'];
allCounts = combineCounts(fj.map(sentences, function(sentence) {
return countWords(tokenize(sentence));
}));
return allCounts(function(error, counts) {
return t.deepEqual(counts, {
hello: 2,
world: 2,
bye: 1,
forkjoin: 2,
goodbye: 1
});
});
});
}).call(this);