-
Notifications
You must be signed in to change notification settings - Fork 5.2k
/
async_multi.js
111 lines (93 loc) · 2.45 KB
/
async_multi.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// This depends on tinytest, so it's a little weird to put it in
// test-helpers, but it'll do for now.
var ExpectationManager = function (test, onComplete) {
var self = this;
self.test = test;
self.onComplete = onComplete;
self.closed = false;
self.dead = false;
self.outstanding = 0;
};
_.extend(ExpectationManager.prototype, {
expect: function (/* arguments */) {
var self = this;
if (typeof arguments[0] === "function")
var expected = arguments[0];
else
var expected = _.toArray(arguments);
if (self.closed)
throw new Error("Too late to add more expectations to the test");
self.outstanding++;
return function (/* arguments */) {
if (self.dead)
return;
if (typeof expected === "function") {
try {
expected.apply({}, arguments);
} catch (e) {
if (self.cancel())
self.test.exception(e);
}
} else {
self.test.equal(_.toArray(arguments), expected);
}
self.outstanding--;
self._check_complete();
};
},
done: function () {
var self = this;
self.closed = true;
self._check_complete();
},
cancel: function () {
var self = this;
if (! self.dead) {
self.dead = true;
return true;
}
return false;
},
_check_complete: function () {
var self = this;
if (!self.outstanding && self.closed && !self.dead) {
self.dead = true;
self.onComplete();
}
}
});
var testAsyncMulti = function (name, funcs) {
var timeout = 15000;
Tinytest.addAsync(name, function (test, onComplete) {
var remaining = _.clone(funcs);
var runNext = function () {
var func = remaining.shift();
if (!func)
onComplete();
else {
var em = new ExpectationManager(test, function () {
Tinytest.clearTimeout(timer);
runNext();
});
var timer = Tinytest.setTimeout(function () {
if (em.cancel()) {
test.fail({type: "timeout", message: "Async batch timed out"});
onComplete();
}
return;
}, timeout);
try {
func(test, _.bind(em.expect, em));
} catch (exception) {
if (em.cancel())
test.exception(exception);
Tinytest.clearTimeout(timer);
// Because we called test.exception, we're not to call onComplete.
return;
}
em.done();
}
};
runNext();
});
};