Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/test/common/cancellation.test.ts
5259 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import assert from 'assert';
6
import { CancellationToken, CancellationTokenSource, CancellationTokenPool } from '../../common/cancellation.js';
7
import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';
8
9
suite('CancellationToken', function () {
10
11
const store = ensureNoDisposablesAreLeakedInTestSuite();
12
13
test('None', () => {
14
assert.strictEqual(CancellationToken.None.isCancellationRequested, false);
15
assert.strictEqual(typeof CancellationToken.None.onCancellationRequested, 'function');
16
});
17
18
test('cancel before token', function () {
19
20
const source = new CancellationTokenSource();
21
assert.strictEqual(source.token.isCancellationRequested, false);
22
source.cancel();
23
24
assert.strictEqual(source.token.isCancellationRequested, true);
25
26
return new Promise<void>(resolve => {
27
source.token.onCancellationRequested(() => resolve());
28
});
29
});
30
31
test('cancel happens only once', function () {
32
33
const source = new CancellationTokenSource();
34
assert.strictEqual(source.token.isCancellationRequested, false);
35
36
let cancelCount = 0;
37
function onCancel() {
38
cancelCount += 1;
39
}
40
41
store.add(source.token.onCancellationRequested(onCancel));
42
43
source.cancel();
44
source.cancel();
45
46
assert.strictEqual(cancelCount, 1);
47
});
48
49
test('cancel calls all listeners', function () {
50
51
let count = 0;
52
53
const source = new CancellationTokenSource();
54
store.add(source.token.onCancellationRequested(() => count++));
55
store.add(source.token.onCancellationRequested(() => count++));
56
store.add(source.token.onCancellationRequested(() => count++));
57
58
source.cancel();
59
assert.strictEqual(count, 3);
60
});
61
62
test('token stays the same', function () {
63
64
let source = new CancellationTokenSource();
65
let token = source.token;
66
assert.ok(token === source.token); // doesn't change on get
67
68
source.cancel();
69
assert.ok(token === source.token); // doesn't change after cancel
70
71
source.cancel();
72
assert.ok(token === source.token); // doesn't change after 2nd cancel
73
74
source = new CancellationTokenSource();
75
source.cancel();
76
token = source.token;
77
assert.ok(token === source.token); // doesn't change on get
78
});
79
80
test('dispose calls no listeners', function () {
81
82
let count = 0;
83
84
const source = new CancellationTokenSource();
85
store.add(source.token.onCancellationRequested(() => count++));
86
87
source.dispose();
88
source.cancel();
89
assert.strictEqual(count, 0);
90
});
91
92
test('dispose calls no listeners (unless told to cancel)', function () {
93
94
let count = 0;
95
96
const source = new CancellationTokenSource();
97
store.add(source.token.onCancellationRequested(() => count++));
98
99
source.dispose(true);
100
// source.cancel();
101
assert.strictEqual(count, 1);
102
});
103
104
test('dispose does not cancel', function () {
105
const source = new CancellationTokenSource();
106
source.dispose();
107
assert.strictEqual(source.token.isCancellationRequested, false);
108
});
109
110
test('parent cancels child', function () {
111
112
const parent = new CancellationTokenSource();
113
const child = new CancellationTokenSource(parent.token);
114
115
let count = 0;
116
store.add(child.token.onCancellationRequested(() => count++));
117
118
parent.cancel();
119
120
assert.strictEqual(count, 1);
121
assert.strictEqual(child.token.isCancellationRequested, true);
122
assert.strictEqual(parent.token.isCancellationRequested, true);
123
124
child.dispose();
125
parent.dispose();
126
});
127
});
128
129
suite('CancellationTokenPool', function () {
130
131
const store = ensureNoDisposablesAreLeakedInTestSuite();
132
133
test('empty pool token is not cancelled', function () {
134
const pool = new CancellationTokenPool();
135
store.add(pool);
136
137
assert.strictEqual(pool.token.isCancellationRequested, false);
138
});
139
140
test('pool token cancels when all tokens are cancelled', function () {
141
const pool = new CancellationTokenPool();
142
store.add(pool);
143
144
const source1 = new CancellationTokenSource();
145
const source2 = new CancellationTokenSource();
146
const source3 = new CancellationTokenSource();
147
148
pool.add(source1.token);
149
pool.add(source2.token);
150
pool.add(source3.token);
151
152
assert.strictEqual(pool.token.isCancellationRequested, false);
153
154
source1.cancel();
155
assert.strictEqual(pool.token.isCancellationRequested, false);
156
157
source2.cancel();
158
assert.strictEqual(pool.token.isCancellationRequested, false);
159
160
source3.cancel();
161
assert.strictEqual(pool.token.isCancellationRequested, true);
162
163
source1.dispose();
164
source2.dispose();
165
source3.dispose();
166
});
167
168
test('pool token fires cancellation event when all tokens are cancelled', function () {
169
return new Promise<void>(resolve => {
170
const pool = new CancellationTokenPool();
171
store.add(pool);
172
173
const source1 = new CancellationTokenSource();
174
const source2 = new CancellationTokenSource();
175
176
pool.add(source1.token);
177
pool.add(source2.token);
178
179
store.add(pool.token.onCancellationRequested(() => resolve()));
180
181
source1.cancel();
182
source2.cancel();
183
184
source1.dispose();
185
source2.dispose();
186
});
187
});
188
189
test('adding already cancelled token counts immediately', function () {
190
const pool = new CancellationTokenPool();
191
store.add(pool);
192
193
const source1 = new CancellationTokenSource();
194
const source2 = new CancellationTokenSource();
195
196
source1.cancel(); // Cancel before adding to pool
197
198
pool.add(source1.token);
199
assert.strictEqual(pool.token.isCancellationRequested, true); // 1 of 1 cancelled, so pool is cancelled
200
201
pool.add(source2.token); // Adding after pool is done should have no effect
202
assert.strictEqual(pool.token.isCancellationRequested, true);
203
204
source2.cancel(); // This should have no effect since pool is already done
205
assert.strictEqual(pool.token.isCancellationRequested, true);
206
207
source1.dispose();
208
source2.dispose();
209
});
210
211
test('adding single already cancelled token cancels pool immediately', function () {
212
const pool = new CancellationTokenPool();
213
store.add(pool);
214
215
const source = new CancellationTokenSource();
216
source.cancel();
217
218
pool.add(source.token);
219
assert.strictEqual(pool.token.isCancellationRequested, true); // 1 of 1 cancelled
220
221
source.dispose();
222
});
223
224
test('adding token after pool is done has no effect', function () {
225
const pool = new CancellationTokenPool();
226
store.add(pool);
227
228
const source1 = new CancellationTokenSource();
229
const source2 = new CancellationTokenSource();
230
231
pool.add(source1.token);
232
source1.cancel(); // Pool should be done now
233
234
assert.strictEqual(pool.token.isCancellationRequested, true);
235
236
// Adding another token should have no effect
237
pool.add(source2.token);
238
source2.cancel();
239
240
assert.strictEqual(pool.token.isCancellationRequested, true);
241
242
source1.dispose();
243
source2.dispose();
244
});
245
246
test('single token pool behaviour', function () {
247
const pool = new CancellationTokenPool();
248
store.add(pool);
249
250
const source = new CancellationTokenSource();
251
pool.add(source.token);
252
253
assert.strictEqual(pool.token.isCancellationRequested, false);
254
255
source.cancel();
256
assert.strictEqual(pool.token.isCancellationRequested, true);
257
258
source.dispose();
259
});
260
261
test('pool with only cancelled tokens', function () {
262
const pool = new CancellationTokenPool();
263
store.add(pool);
264
265
const source1 = new CancellationTokenSource();
266
const source2 = new CancellationTokenSource();
267
268
source1.cancel();
269
source2.cancel();
270
271
pool.add(source1.token);
272
pool.add(source2.token);
273
274
assert.strictEqual(pool.token.isCancellationRequested, true);
275
276
source1.dispose();
277
source2.dispose();
278
});
279
});
280
281