Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/base/test/common/cancelPreviousCalls.test.ts
3296 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
6
import assert from 'assert';
7
import { Disposable } from '../../common/lifecycle.js';
8
import { CancellationToken } from '../../common/cancellation.js';
9
import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js';
10
import { cancelPreviousCalls } from '../../common/decorators/cancelPreviousCalls.js';
11
12
suite('cancelPreviousCalls decorator', () => {
13
const disposables = ensureNoDisposablesAreLeakedInTestSuite();
14
15
class MockDisposable extends Disposable {
16
/**
17
* Arguments that the {@linkcode doSomethingAsync} method was called with.
18
*/
19
private readonly callArgs1: ([number, string, CancellationToken | undefined])[] = [];
20
21
/**
22
* Arguments that the {@linkcode doSomethingElseAsync} method was called with.
23
*/
24
private readonly callArgs2: ([number, string, CancellationToken | undefined])[] = [];
25
26
/**
27
* Returns the arguments that the {@linkcode doSomethingAsync} method was called with.
28
*/
29
public get callArguments1() {
30
return this.callArgs1;
31
}
32
33
/**
34
* Returns the arguments that the {@linkcode doSomethingElseAsync} method was called with.
35
*/
36
public get callArguments2() {
37
return this.callArgs2;
38
}
39
40
@cancelPreviousCalls
41
async doSomethingAsync(arg1: number, arg2: string, cancellationToken?: CancellationToken): Promise<void> {
42
this.callArgs1.push([arg1, arg2, cancellationToken]);
43
44
await new Promise(resolve => setTimeout(resolve, 25));
45
}
46
47
@cancelPreviousCalls
48
async doSomethingElseAsync(arg1: number, arg2: string, cancellationToken?: CancellationToken): Promise<void> {
49
this.callArgs2.push([arg1, arg2, cancellationToken]);
50
51
await new Promise(resolve => setTimeout(resolve, 25));
52
}
53
}
54
55
test('should call method with CancellationToken', async () => {
56
const instance = disposables.add(new MockDisposable());
57
58
await instance.doSomethingAsync(1, 'foo');
59
60
const callArguments = instance.callArguments1;
61
assert.strictEqual(
62
callArguments.length,
63
1,
64
`The 'doSomethingAsync' method must be called just once.`,
65
);
66
67
const args = callArguments[0];
68
assert(
69
args.length === 3,
70
`The 'doSomethingAsync' method must be called with '3' arguments, got '${args.length}'.`,
71
);
72
73
const arg1 = args[0];
74
const arg2 = args[1];
75
const arg3 = args[2];
76
77
assert.strictEqual(
78
arg1,
79
1,
80
`The 'doSomethingAsync' method call must have the correct 1st argument.`,
81
);
82
83
assert.strictEqual(
84
arg2,
85
'foo',
86
`The 'doSomethingAsync' method call must have the correct 2nd argument.`,
87
);
88
89
assert(
90
CancellationToken.isCancellationToken(arg3),
91
`The last argument of the 'doSomethingAsync' method must be a 'CancellationToken', got '${arg3}'.`,
92
);
93
94
assert(
95
arg3.isCancellationRequested === false,
96
`The 'CancellationToken' argument must not yet be cancelled.`,
97
);
98
99
assert(
100
instance.callArguments2.length === 0,
101
`The 'doSomethingElseAsync' method must not be called.`,
102
);
103
});
104
105
test('cancel token of the previous call when method is called again', async () => {
106
const instance = disposables.add(new MockDisposable());
107
108
instance.doSomethingAsync(1, 'foo');
109
await new Promise(resolve => setTimeout(resolve, 10));
110
instance.doSomethingAsync(2, 'bar');
111
112
const callArguments = instance.callArguments1;
113
assert.strictEqual(
114
callArguments.length,
115
2,
116
`The 'doSomethingAsync' method must be called twice.`,
117
);
118
119
const call1Args = callArguments[0];
120
assert(
121
call1Args.length === 3,
122
`The first call of the 'doSomethingAsync' method must have '3' arguments, got '${call1Args.length}'.`,
123
);
124
125
assert.strictEqual(
126
call1Args[0],
127
1,
128
`The first call of the 'doSomethingAsync' method must have the correct 1st argument.`,
129
);
130
131
assert.strictEqual(
132
call1Args[1],
133
'foo',
134
`The first call of the 'doSomethingAsync' method must have the correct 2nd argument.`,
135
);
136
137
assert(
138
CancellationToken.isCancellationToken(call1Args[2]),
139
`The first call of the 'doSomethingAsync' method must have the 'CancellationToken' as the 3rd argument.`,
140
);
141
142
assert(
143
call1Args[2].isCancellationRequested === true,
144
`The 'CancellationToken' of the first call must be cancelled.`,
145
);
146
147
const call2Args = callArguments[1];
148
assert(
149
call2Args.length === 3,
150
`The second call of the 'doSomethingAsync' method must have '3' arguments, got '${call1Args.length}'.`,
151
);
152
153
assert.strictEqual(
154
call2Args[0],
155
2,
156
`The second call of the 'doSomethingAsync' method must have the correct 1st argument.`,
157
);
158
159
assert.strictEqual(
160
call2Args[1],
161
'bar',
162
`The second call of the 'doSomethingAsync' method must have the correct 2nd argument.`,
163
);
164
165
assert(
166
CancellationToken.isCancellationToken(call2Args[2]),
167
`The second call of the 'doSomethingAsync' method must have the 'CancellationToken' as the 3rd argument.`,
168
);
169
170
assert(
171
call2Args[2].isCancellationRequested === false,
172
`The 'CancellationToken' of the second call must be cancelled.`,
173
);
174
175
assert(
176
instance.callArguments2.length === 0,
177
`The 'doSomethingElseAsync' method must not be called.`,
178
);
179
});
180
181
test('different method calls must not interfere with each other', async () => {
182
const instance = disposables.add(new MockDisposable());
183
184
instance.doSomethingAsync(10, 'baz');
185
await new Promise(resolve => setTimeout(resolve, 10));
186
instance.doSomethingElseAsync(25, 'qux');
187
188
assert.strictEqual(
189
instance.callArguments1.length,
190
1,
191
`The 'doSomethingAsync' method must be called once.`,
192
);
193
194
const call1Args = instance.callArguments1[0];
195
assert(
196
call1Args.length === 3,
197
`The first call of the 'doSomethingAsync' method must have '3' arguments, got '${call1Args.length}'.`,
198
);
199
200
assert.strictEqual(
201
call1Args[0],
202
10,
203
`The first call of the 'doSomethingAsync' method must have the correct 1st argument.`,
204
);
205
206
assert.strictEqual(
207
call1Args[1],
208
'baz',
209
`The first call of the 'doSomethingAsync' method must have the correct 2nd argument.`,
210
);
211
212
assert(
213
CancellationToken.isCancellationToken(call1Args[2]),
214
`The first call of the 'doSomethingAsync' method must have the 'CancellationToken' as the 3rd argument.`,
215
);
216
217
assert(
218
call1Args[2].isCancellationRequested === false,
219
`The 'CancellationToken' of the first call must not be cancelled.`,
220
);
221
222
assert.strictEqual(
223
instance.callArguments2.length,
224
1,
225
`The 'doSomethingElseAsync' method must be called once.`,
226
);
227
228
const call2Args = instance.callArguments2[0];
229
assert(
230
call2Args.length === 3,
231
`The first call of the 'doSomethingElseAsync' method must have '3' arguments, got '${call1Args.length}'.`,
232
);
233
234
assert.strictEqual(
235
call2Args[0],
236
25,
237
`The first call of the 'doSomethingElseAsync' method must have the correct 1st argument.`,
238
);
239
240
assert.strictEqual(
241
call2Args[1],
242
'qux',
243
`The first call of the 'doSomethingElseAsync' method must have the correct 2nd argument.`,
244
);
245
246
assert(
247
CancellationToken.isCancellationToken(call2Args[2]),
248
`The first call of the 'doSomethingElseAsync' method must have the 'CancellationToken' as the 3rd argument.`,
249
);
250
251
assert(
252
call2Args[2].isCancellationRequested === false,
253
`The 'CancellationToken' of the second call must be cancelled.`,
254
);
255
256
instance.doSomethingElseAsync(105, 'uxi');
257
258
assert.strictEqual(
259
instance.callArguments1.length,
260
1,
261
`The 'doSomethingAsync' method must be called once.`,
262
);
263
264
assert.strictEqual(
265
instance.callArguments2.length,
266
2,
267
`The 'doSomethingElseAsync' method must be called twice.`,
268
);
269
270
assert(
271
call1Args[2].isCancellationRequested === false,
272
`The 'CancellationToken' of the first call must not be cancelled.`,
273
);
274
275
const call3Args = instance.callArguments2[1];
276
assert(
277
CancellationToken.isCancellationToken(call3Args[2]),
278
`The last argument of the second call of the 'doSomethingElseAsync' method must be a 'CancellationToken'.`,
279
);
280
281
assert(
282
call2Args[2].isCancellationRequested,
283
`The 'CancellationToken' of the first call must be cancelled.`,
284
);
285
286
assert(
287
call3Args[2].isCancellationRequested === false,
288
`The 'CancellationToken' of the second call must not be cancelled.`,
289
);
290
291
assert.strictEqual(
292
call3Args[0],
293
105,
294
`The second call of the 'doSomethingElseAsync' method must have the correct 1st argument.`,
295
);
296
297
assert.strictEqual(
298
call3Args[1],
299
'uxi',
300
`The second call of the 'doSomethingElseAsync' method must have the correct 2nd argument.`,
301
);
302
});
303
});
304
305