Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/unit/assert.js
3520 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
7
// UTILITY
8
9
// Object.create compatible in IE
10
const create = Object.create || function (p) {
11
if (!p) { throw Error('no type'); }
12
function f() { }
13
f.prototype = p;
14
return new f();
15
};
16
17
// UTILITY
18
var util = {
19
inherits: function (ctor, superCtor) {
20
ctor.super_ = superCtor;
21
ctor.prototype = create(superCtor.prototype, {
22
constructor: {
23
value: ctor,
24
enumerable: false,
25
writable: true,
26
configurable: true
27
}
28
});
29
},
30
isArray: function (ar) {
31
return Array.isArray(ar);
32
},
33
isBoolean: function (arg) {
34
return typeof arg === 'boolean';
35
},
36
isNull: function (arg) {
37
return arg === null;
38
},
39
isNullOrUndefined: function (arg) {
40
return arg == null;
41
},
42
isNumber: function (arg) {
43
return typeof arg === 'number';
44
},
45
isString: function (arg) {
46
return typeof arg === 'string';
47
},
48
isSymbol: function (arg) {
49
return typeof arg === 'symbol';
50
},
51
isUndefined: function (arg) {
52
return arg === undefined;
53
},
54
isRegExp: function (re) {
55
return util.isObject(re) && util.objectToString(re) === '[object RegExp]';
56
},
57
isObject: function (arg) {
58
return typeof arg === 'object' && arg !== null;
59
},
60
isDate: function (d) {
61
return util.isObject(d) && util.objectToString(d) === '[object Date]';
62
},
63
isError: function (e) {
64
return isObject(e) &&
65
(objectToString(e) === '[object Error]' || e instanceof Error);
66
},
67
isFunction: function (arg) {
68
return typeof arg === 'function';
69
},
70
isPrimitive: function (arg) {
71
return arg === null ||
72
typeof arg === 'boolean' ||
73
typeof arg === 'number' ||
74
typeof arg === 'string' ||
75
typeof arg === 'symbol' || // ES6 symbol
76
typeof arg === 'undefined';
77
},
78
objectToString: function (o) {
79
return Object.prototype.toString.call(o);
80
}
81
};
82
83
const pSlice = Array.prototype.slice;
84
85
// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
86
const Object_keys = typeof Object.keys === 'function' ? Object.keys : (function () {
87
const hasOwnProperty = Object.prototype.hasOwnProperty,
88
hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
89
dontEnums = [
90
'toString',
91
'toLocaleString',
92
'valueOf',
93
'hasOwnProperty',
94
'isPrototypeOf',
95
'propertyIsEnumerable',
96
'constructor'
97
],
98
dontEnumsLength = dontEnums.length;
99
100
return function (obj) {
101
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
102
throw new TypeError('Object.keys called on non-object');
103
}
104
105
let result = [], prop, i;
106
107
for (prop in obj) {
108
if (hasOwnProperty.call(obj, prop)) {
109
result.push(prop);
110
}
111
}
112
113
if (hasDontEnumBug) {
114
for (i = 0; i < dontEnumsLength; i++) {
115
if (hasOwnProperty.call(obj, dontEnums[i])) {
116
result.push(dontEnums[i]);
117
}
118
}
119
}
120
return result;
121
};
122
})();
123
124
// 1. The assert module provides functions that throw
125
// AssertionError's when particular conditions are not met. The
126
// assert module must conform to the following interface.
127
128
const assert = ok;
129
130
// 2. The AssertionError is defined in assert.
131
// new assert.AssertionError({ message: message,
132
// actual: actual,
133
// expected: expected })
134
135
assert.AssertionError = function AssertionError(options) {
136
this.name = 'AssertionError';
137
this.actual = options.actual;
138
this.expected = options.expected;
139
this.operator = options.operator;
140
if (options.message) {
141
this.message = options.message;
142
this.generatedMessage = false;
143
} else {
144
this.message = getMessage(this);
145
this.generatedMessage = true;
146
}
147
const stackStartFunction = options.stackStartFunction || fail;
148
if (Error.captureStackTrace) {
149
Error.captureStackTrace(this, stackStartFunction);
150
} else {
151
// try to throw an error now, and from the stack property
152
// work out the line that called in to assert.js.
153
try {
154
this.stack = (new Error).stack.toString();
155
} catch (e) { }
156
}
157
};
158
159
// assert.AssertionError instanceof Error
160
util.inherits(assert.AssertionError, Error);
161
162
function replacer(key, value) {
163
if (util.isUndefined(value)) {
164
return '' + value;
165
}
166
if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
167
return value.toString();
168
}
169
if (util.isFunction(value) || util.isRegExp(value)) {
170
return value.toString();
171
}
172
return value;
173
}
174
175
function truncate(s, n) {
176
if (util.isString(s)) {
177
return s.length < n ? s : s.slice(0, n);
178
} else {
179
return s;
180
}
181
}
182
183
function getMessage(self) {
184
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
185
self.operator + ' ' +
186
truncate(JSON.stringify(self.expected, replacer), 128);
187
}
188
189
// At present only the three keys mentioned above are used and
190
// understood by the spec. Implementations or sub modules can pass
191
// other keys to the AssertionError's constructor - they will be
192
// ignored.
193
194
// 3. All of the following functions must throw an AssertionError
195
// when a corresponding condition is not met, with a message that
196
// may be undefined if not provided. All assertion methods provide
197
// both the actual and expected values to the assertion error for
198
// display purposes.
199
200
export function fail(actual, expected, message, operator, stackStartFunction) {
201
throw new assert.AssertionError({
202
message: message,
203
actual: actual,
204
expected: expected,
205
operator: operator,
206
stackStartFunction: stackStartFunction
207
});
208
}
209
210
// EXTENSION! allows for well behaved errors defined elsewhere.
211
assert.fail = fail;
212
213
// 4. Pure assertion tests whether a value is truthy, as determined
214
// by !!guard.
215
// assert.ok(guard, message_opt);
216
// This statement is equivalent to assert.equal(true, !!guard,
217
// message_opt);. To test strictly for the value true, use
218
// assert.strictEqual(true, guard, message_opt);.
219
220
export function ok(value, message) {
221
if (!value) { fail(value, true, message, '==', assert.ok); }
222
}
223
assert.ok = ok;
224
225
// 5. The equality assertion tests shallow, coercive equality with
226
// ==.
227
// assert.equal(actual, expected, message_opt);
228
229
assert.equal = function equal(actual, expected, message) {
230
if (actual != expected) { fail(actual, expected, message, '==', assert.equal); }
231
};
232
233
// 6. The non-equality assertion tests for whether two objects are not equal
234
// with != assert.notEqual(actual, expected, message_opt);
235
236
assert.notEqual = function notEqual(actual, expected, message) {
237
if (actual == expected) {
238
fail(actual, expected, message, '!=', assert.notEqual);
239
}
240
};
241
242
// 7. The equivalence assertion tests a deep equality relation.
243
// assert.deepEqual(actual, expected, message_opt);
244
245
assert.deepEqual = function deepEqual(actual, expected, message) {
246
if (!_deepEqual(actual, expected, false)) {
247
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
248
}
249
};
250
251
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
252
if (!_deepEqual(actual, expected, true)) {
253
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
254
}
255
};
256
257
function _deepEqual(actual, expected, strict) {
258
// 7.1. All identical values are equivalent, as determined by ===.
259
if (actual === expected) {
260
return true;
261
// } else if (actual instanceof Buffer && expected instanceof Buffer) {
262
// return compare(actual, expected) === 0;
263
264
// 7.2. If the expected value is a Date object, the actual value is
265
// equivalent if it is also a Date object that refers to the same time.
266
} else if (util.isDate(actual) && util.isDate(expected)) {
267
return actual.getTime() === expected.getTime();
268
269
// 7.3 If the expected value is a RegExp object, the actual value is
270
// equivalent if it is also a RegExp object with the same source and
271
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
272
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
273
return actual.source === expected.source &&
274
actual.global === expected.global &&
275
actual.multiline === expected.multiline &&
276
actual.lastIndex === expected.lastIndex &&
277
actual.ignoreCase === expected.ignoreCase;
278
279
// 7.4. Other pairs that do not both pass typeof value == 'object',
280
// equivalence is determined by ==.
281
} else if ((actual === null || typeof actual !== 'object') &&
282
(expected === null || typeof expected !== 'object')) {
283
return strict ? actual === expected : actual == expected;
284
285
// 7.5 For all other Object pairs, including Array objects, equivalence is
286
// determined by having the same number of owned properties (as verified
287
// with Object.prototype.hasOwnProperty.call), the same set of keys
288
// (although not necessarily the same order), equivalent values for every
289
// corresponding key, and an identical 'prototype' property. Note: this
290
// accounts for both named and indexed properties on Arrays.
291
} else {
292
return objEquiv(actual, expected, strict);
293
}
294
}
295
296
function isArguments(object) {
297
return Object.prototype.toString.call(object) == '[object Arguments]';
298
}
299
300
function objEquiv(a, b, strict) {
301
if (a === null || a === undefined || b === null || b === undefined) { return false; }
302
// if one is a primitive, the other must be same
303
if (util.isPrimitive(a) || util.isPrimitive(b)) { return a === b; }
304
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) { return false; }
305
const aIsArgs = isArguments(a),
306
bIsArgs = isArguments(b);
307
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) { return false; }
308
if (aIsArgs) {
309
a = pSlice.call(a);
310
b = pSlice.call(b);
311
return _deepEqual(a, b, strict);
312
}
313
let ka = Object.keys(a),
314
kb = Object.keys(b),
315
key, i;
316
// having the same number of owned properties (keys incorporates
317
// hasOwnProperty)
318
if (ka.length !== kb.length) { return false; }
319
//the same set of keys (although not necessarily the same order),
320
ka.sort();
321
kb.sort();
322
//~~~cheap key test
323
for (i = ka.length - 1; i >= 0; i--) {
324
if (ka[i] !== kb[i]) { return false; }
325
}
326
//equivalent values for every corresponding key, and
327
//~~~possibly expensive deep test
328
for (i = ka.length - 1; i >= 0; i--) {
329
key = ka[i];
330
if (!_deepEqual(a[key], b[key], strict)) { return false; }
331
}
332
return true;
333
}
334
335
// 8. The non-equivalence assertion tests for any deep inequality.
336
// assert.notDeepEqual(actual, expected, message_opt);
337
338
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
339
if (_deepEqual(actual, expected, false)) {
340
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
341
}
342
};
343
344
assert.notDeepStrictEqual = notDeepStrictEqual;
345
export function notDeepStrictEqual(actual, expected, message) {
346
if (_deepEqual(actual, expected, true)) {
347
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
348
}
349
}
350
351
352
// 9. The strict equality assertion tests strict equality, as determined by ===.
353
// assert.strictEqual(actual, expected, message_opt);
354
355
assert.strictEqual = function strictEqual(actual, expected, message) {
356
if (actual !== expected) {
357
fail(actual, expected, message, '===', assert.strictEqual);
358
}
359
};
360
361
// 10. The strict non-equality assertion tests for strict inequality, as
362
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
363
364
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
365
if (actual === expected) {
366
fail(actual, expected, message, '!==', assert.notStrictEqual);
367
}
368
};
369
370
function expectedException(actual, expected) {
371
if (!actual || !expected) {
372
return false;
373
}
374
375
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
376
return expected.test(actual);
377
} else if (actual instanceof expected) {
378
return true;
379
} else if (expected.call({}, actual) === true) {
380
return true;
381
}
382
383
return false;
384
}
385
386
function _throws(shouldThrow, block, expected, message) {
387
let actual;
388
389
if (typeof block !== 'function') {
390
throw new TypeError('block must be a function');
391
}
392
393
if (typeof expected === 'string') {
394
message = expected;
395
expected = null;
396
}
397
398
try {
399
block();
400
} catch (e) {
401
actual = e;
402
}
403
404
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
405
(message ? ' ' + message : '.');
406
407
if (shouldThrow && !actual) {
408
fail(actual, expected, 'Missing expected exception' + message);
409
}
410
411
if (!shouldThrow && expectedException(actual, expected)) {
412
fail(actual, expected, 'Got unwanted exception' + message);
413
}
414
415
if ((shouldThrow && actual && expected &&
416
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
417
throw actual;
418
}
419
}
420
421
// 11. Expected to throw an error:
422
// assert.throws(block, Error_opt, message_opt);
423
424
assert.throws = function (block, /*optional*/error, /*optional*/message) {
425
_throws.apply(this, [true].concat(pSlice.call(arguments)));
426
};
427
428
// EXTENSION! This is annoying to write outside this module.
429
assert.doesNotThrow = function (block, /*optional*/message) {
430
_throws.apply(this, [false].concat(pSlice.call(arguments)));
431
};
432
433
assert.ifError = function (err) { if (err) { throw err; } };
434
435
function checkIsPromise(obj) {
436
return (obj !== null && typeof obj === 'object' &&
437
typeof obj.then === 'function' &&
438
typeof obj.catch === 'function');
439
}
440
441
const NO_EXCEPTION_SENTINEL = {};
442
async function waitForActual(promiseFn) {
443
let resultPromise;
444
if (typeof promiseFn === 'function') {
445
// Return a rejected promise if `promiseFn` throws synchronously.
446
resultPromise = promiseFn();
447
// Fail in case no promise is returned.
448
if (!checkIsPromise(resultPromise)) {
449
throw new Error('ERR_INVALID_RETURN_VALUE: promiseFn did not return Promise. ' + resultPromise);
450
}
451
} else if (checkIsPromise(promiseFn)) {
452
resultPromise = promiseFn;
453
} else {
454
throw new Error('ERR_INVALID_ARG_TYPE: promiseFn is not Function or Promise. ' + promiseFn);
455
}
456
457
try {
458
await resultPromise;
459
} catch (e) {
460
return e;
461
}
462
return NO_EXCEPTION_SENTINEL;
463
}
464
465
function expectsError(shouldHaveError, actual, message) {
466
if (shouldHaveError && actual === NO_EXCEPTION_SENTINEL) {
467
fail(undefined, 'Error', `Missing expected rejection${message ? ': ' + message : ''}`)
468
} else if (!shouldHaveError && actual !== NO_EXCEPTION_SENTINEL) {
469
fail(actual, undefined, `Got unexpected rejection (${actual.message})${message ? ': ' + message : ''}`)
470
}
471
}
472
473
assert.rejects = async function rejects(promiseFn, message) {
474
expectsError(true, await waitForActual(promiseFn), message);
475
};
476
477
assert.doesNotReject = async function doesNotReject(fn, message) {
478
expectsError(false, await waitForActual(fn), message);
479
};
480
481
// ESM export
482
export default assert;
483
export const AssertionError = assert.AssertionError
484
// export const fail = assert.fail
485
// export const ok = assert.ok
486
export const equal = assert.equal
487
export const notEqual = assert.notEqual
488
export const deepEqual = assert.deepEqual
489
export const deepStrictEqual = assert.deepStrictEqual
490
export const notDeepEqual = assert.notDeepEqual
491
// export const notDeepStrictEqual = assert.notDeepStrictEqual
492
export const strictEqual = assert.strictEqual
493
export const notStrictEqual = assert.notStrictEqual
494
export const throws = assert.throws
495
export const doesNotThrow = assert.doesNotThrow
496
export const ifError = assert.ifError
497
export const rejects = assert.rejects
498
export const doesNotReject = assert.doesNotReject
499
500