您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

assert.js 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. /*!
  2. * assert.js - assertions for javascript
  3. * Copyright (c) 2018, Christopher Jeffrey (MIT License).
  4. * https://github.com/chjj/bsert
  5. */
  6. 'use strict';
  7. /**
  8. * AssertionError
  9. */
  10. class AssertionError extends Error {
  11. constructor(options) {
  12. if (typeof options === 'string')
  13. options = { message: options };
  14. if (options === null || typeof options !== 'object')
  15. options = {};
  16. let message = null;
  17. let operator = 'fail';
  18. let generatedMessage = Boolean(options.generatedMessage);
  19. if (options.message != null)
  20. message = toString(options.message);
  21. if (typeof options.operator === 'string')
  22. operator = options.operator;
  23. if (message == null) {
  24. if (operator === 'fail') {
  25. message = 'Assertion failed.';
  26. } else {
  27. const a = stringify(options.actual);
  28. const b = stringify(options.expected);
  29. message = `${a} ${operator} ${b}`;
  30. }
  31. generatedMessage = true;
  32. }
  33. super(message);
  34. let start = this.constructor;
  35. if (typeof options.stackStartFunction === 'function')
  36. start = options.stackStartFunction;
  37. else if (typeof options.stackStartFn === 'function')
  38. start = options.stackStartFn;
  39. this.type = 'AssertionError';
  40. this.name = 'AssertionError [ERR_ASSERTION]';
  41. this.code = 'ERR_ASSERTION';
  42. this.generatedMessage = generatedMessage;
  43. this.actual = options.actual;
  44. this.expected = options.expected;
  45. this.operator = operator;
  46. if (Error.captureStackTrace)
  47. Error.captureStackTrace(this, start);
  48. }
  49. }
  50. /*
  51. * Assert
  52. */
  53. function assert(value, message) {
  54. if (!value) {
  55. let generatedMessage = false;
  56. if (arguments.length === 0) {
  57. message = 'No value argument passed to `assert()`.';
  58. generatedMessage = true;
  59. } else if (message == null) {
  60. message = 'Assertion failed.';
  61. generatedMessage = true;
  62. } else if (isError(message)) {
  63. throw message;
  64. }
  65. throw new AssertionError({
  66. message,
  67. actual: value,
  68. expected: true,
  69. operator: '==',
  70. generatedMessage,
  71. stackStartFn: assert
  72. });
  73. }
  74. }
  75. function equal(actual, expected, message) {
  76. if (!Object.is(actual, expected)) {
  77. if (isError(message))
  78. throw message;
  79. throw new AssertionError({
  80. message,
  81. actual,
  82. expected,
  83. operator: 'strictEqual',
  84. stackStartFn: equal
  85. });
  86. }
  87. }
  88. function notEqual(actual, expected, message) {
  89. if (Object.is(actual, expected)) {
  90. if (isError(message))
  91. throw message;
  92. throw new AssertionError({
  93. message,
  94. actual,
  95. expected,
  96. operator: 'notStrictEqual',
  97. stackStartFn: notEqual
  98. });
  99. }
  100. }
  101. function fail(message) {
  102. let generatedMessage = false;
  103. if (isError(message))
  104. throw message;
  105. if (message == null) {
  106. message = 'Assertion failed.';
  107. generatedMessage = true;
  108. }
  109. throw new AssertionError({
  110. message,
  111. actual: false,
  112. expected: true,
  113. operator: 'fail',
  114. generatedMessage,
  115. stackStartFn: fail
  116. });
  117. }
  118. function throws(func, expected, message) {
  119. if (typeof expected === 'string') {
  120. message = expected;
  121. expected = undefined;
  122. }
  123. let thrown = false;
  124. let err = null;
  125. enforce(typeof func === 'function', 'func', 'function');
  126. try {
  127. func();
  128. } catch (e) {
  129. thrown = true;
  130. err = e;
  131. }
  132. if (!thrown) {
  133. let generatedMessage = false;
  134. if (message == null) {
  135. message = 'Missing expected exception.';
  136. generatedMessage = true;
  137. }
  138. throw new AssertionError({
  139. message,
  140. actual: undefined,
  141. expected,
  142. operator: 'throws',
  143. generatedMessage,
  144. stackStartFn: throws
  145. });
  146. }
  147. if (!testError(err, expected, message, throws))
  148. throw err;
  149. }
  150. function doesNotThrow(func, expected, message) {
  151. if (typeof expected === 'string') {
  152. message = expected;
  153. expected = undefined;
  154. }
  155. let thrown = false;
  156. let err = null;
  157. enforce(typeof func === 'function', 'func', 'function');
  158. try {
  159. func();
  160. } catch (e) {
  161. thrown = true;
  162. err = e;
  163. }
  164. if (!thrown)
  165. return;
  166. if (testError(err, expected, message, doesNotThrow)) {
  167. let generatedMessage = false;
  168. if (message == null) {
  169. message = 'Got unwanted exception.';
  170. generatedMessage = true;
  171. }
  172. throw new AssertionError({
  173. message,
  174. actual: err,
  175. expected,
  176. operator: 'doesNotThrow',
  177. generatedMessage,
  178. stackStartFn: doesNotThrow
  179. });
  180. }
  181. throw err;
  182. }
  183. async function rejects(func, expected, message) {
  184. if (typeof expected === 'string') {
  185. message = expected;
  186. expected = undefined;
  187. }
  188. let thrown = false;
  189. let err = null;
  190. if (typeof func !== 'function')
  191. enforce(isPromise(func), 'func', 'promise');
  192. try {
  193. if (isPromise(func))
  194. await func;
  195. else
  196. await func();
  197. } catch (e) {
  198. thrown = true;
  199. err = e;
  200. }
  201. if (!thrown) {
  202. let generatedMessage = false;
  203. if (message == null) {
  204. message = 'Missing expected rejection.';
  205. generatedMessage = true;
  206. }
  207. throw new AssertionError({
  208. message,
  209. actual: undefined,
  210. expected,
  211. operator: 'rejects',
  212. generatedMessage,
  213. stackStartFn: rejects
  214. });
  215. }
  216. if (!testError(err, expected, message, rejects))
  217. throw err;
  218. }
  219. async function doesNotReject(func, expected, message) {
  220. if (typeof expected === 'string') {
  221. message = expected;
  222. expected = undefined;
  223. }
  224. let thrown = false;
  225. let err = null;
  226. if (typeof func !== 'function')
  227. enforce(isPromise(func), 'func', 'promise');
  228. try {
  229. if (isPromise(func))
  230. await func;
  231. else
  232. await func();
  233. } catch (e) {
  234. thrown = true;
  235. err = e;
  236. }
  237. if (!thrown)
  238. return;
  239. if (testError(err, expected, message, doesNotReject)) {
  240. let generatedMessage = false;
  241. if (message == null) {
  242. message = 'Got unwanted rejection.';
  243. generatedMessage = true;
  244. }
  245. throw new AssertionError({
  246. message,
  247. actual: undefined,
  248. expected,
  249. operator: 'doesNotReject',
  250. generatedMessage,
  251. stackStartFn: doesNotReject
  252. });
  253. }
  254. throw err;
  255. }
  256. function ifError(err) {
  257. if (err != null) {
  258. let message = 'ifError got unwanted exception: ';
  259. if (typeof err === 'object' && typeof err.message === 'string') {
  260. if (err.message.length === 0 && err.constructor)
  261. message += err.constructor.name;
  262. else
  263. message += err.message;
  264. } else {
  265. message += stringify(err);
  266. }
  267. throw new AssertionError({
  268. message,
  269. actual: err,
  270. expected: null,
  271. operator: 'ifError',
  272. generatedMessage: true,
  273. stackStartFn: ifError
  274. });
  275. }
  276. }
  277. function deepEqual(actual, expected, message) {
  278. if (!isDeepEqual(actual, expected, false)) {
  279. if (isError(message))
  280. throw message;
  281. throw new AssertionError({
  282. message,
  283. actual,
  284. expected,
  285. operator: 'deepStrictEqual',
  286. stackStartFn: deepEqual
  287. });
  288. }
  289. }
  290. function notDeepEqual(actual, expected, message) {
  291. if (isDeepEqual(actual, expected, true)) {
  292. if (isError(message))
  293. throw message;
  294. throw new AssertionError({
  295. message,
  296. actual,
  297. expected,
  298. operator: 'notDeepStrictEqual',
  299. stackStartFn: notDeepEqual
  300. });
  301. }
  302. }
  303. function bufferEqual(actual, expected, enc, message) {
  304. if (!isEncoding(enc)) {
  305. message = enc;
  306. enc = null;
  307. }
  308. if (enc == null)
  309. enc = 'hex';
  310. expected = bufferize(actual, expected, enc);
  311. enforce(isBuffer(actual), 'actual', 'buffer');
  312. enforce(isBuffer(expected), 'expected', 'buffer');
  313. if (actual !== expected && !actual.equals(expected)) {
  314. if (isError(message))
  315. throw message;
  316. throw new AssertionError({
  317. message,
  318. actual: actual.toString(enc),
  319. expected: expected.toString(enc),
  320. operator: 'bufferEqual',
  321. stackStartFn: bufferEqual
  322. });
  323. }
  324. }
  325. function notBufferEqual(actual, expected, enc, message) {
  326. if (!isEncoding(enc)) {
  327. message = enc;
  328. enc = null;
  329. }
  330. if (enc == null)
  331. enc = 'hex';
  332. expected = bufferize(actual, expected, enc);
  333. enforce(isBuffer(actual), 'actual', 'buffer');
  334. enforce(isBuffer(expected), 'expected', 'buffer');
  335. if (actual === expected || actual.equals(expected)) {
  336. if (isError(message))
  337. throw message;
  338. throw new AssertionError({
  339. message,
  340. actual: actual.toString(enc),
  341. expected: expected.toString(enc),
  342. operator: 'notBufferEqual',
  343. stackStartFn: notBufferEqual
  344. });
  345. }
  346. }
  347. function enforce(value, name, type) {
  348. if (!value) {
  349. let msg;
  350. if (name == null) {
  351. msg = 'Invalid type for parameter.';
  352. } else {
  353. if (type == null)
  354. msg = `Invalid type for "${name}".`;
  355. else
  356. msg = `"${name}" must be a(n) ${type}.`;
  357. }
  358. const err = new TypeError(msg);
  359. if (Error.captureStackTrace)
  360. Error.captureStackTrace(err, enforce);
  361. throw err;
  362. }
  363. }
  364. function range(value, name) {
  365. if (!value) {
  366. const msg = name != null
  367. ? `"${name}" is out of range.`
  368. : 'Parameter is out of range.';
  369. const err = new RangeError(msg);
  370. if (Error.captureStackTrace)
  371. Error.captureStackTrace(err, range);
  372. throw err;
  373. }
  374. }
  375. /*
  376. * Stringification
  377. */
  378. function stringify(value) {
  379. switch (typeof value) {
  380. case 'undefined':
  381. return 'undefined';
  382. case 'object':
  383. if (value === null)
  384. return 'null';
  385. return `[${objectName(value)}]`;
  386. case 'boolean':
  387. return `${value}`;
  388. case 'number':
  389. return `${value}`;
  390. case 'string':
  391. if (value.length > 80)
  392. value = `${value.substring(0, 77)}...`;
  393. return JSON.stringify(value);
  394. case 'symbol':
  395. return tryString(value);
  396. case 'function':
  397. return `[${funcName(value)}]`;
  398. case 'bigint':
  399. return `${value}n`;
  400. default:
  401. return `[${typeof value}]`;
  402. }
  403. }
  404. function toString(value) {
  405. if (typeof value === 'string')
  406. return value;
  407. if (isError(value))
  408. return tryString(value);
  409. return stringify(value);
  410. }
  411. function tryString(value) {
  412. try {
  413. return String(value);
  414. } catch (e) {
  415. return 'Object';
  416. }
  417. }
  418. /*
  419. * Error Testing
  420. */
  421. function testError(err, expected, message, func) {
  422. if (expected == null)
  423. return true;
  424. if (isRegExp(expected))
  425. return expected.test(err);
  426. if (typeof expected !== 'function') {
  427. if (func === doesNotThrow || func === doesNotReject)
  428. throw new TypeError('"expected" must not be an object.');
  429. if (typeof expected !== 'object')
  430. throw new TypeError('"expected" must be an object.');
  431. let generatedMessage = false;
  432. if (message == null) {
  433. const name = func === rejects ? 'rejection' : 'exception';
  434. message = `Missing expected ${name}.`;
  435. generatedMessage = true;
  436. }
  437. if (err == null || typeof err !== 'object') {
  438. throw new AssertionError({
  439. actual: err,
  440. expected,
  441. message,
  442. operator: func.name,
  443. generatedMessage,
  444. stackStartFn: func
  445. });
  446. }
  447. const keys = Object.keys(expected);
  448. if (isError(expected))
  449. keys.push('name', 'message');
  450. if (keys.length === 0)
  451. throw new TypeError('"expected" may not be an empty object.');
  452. for (const key of keys) {
  453. const expect = expected[key];
  454. const value = err[key];
  455. if (typeof value === 'string'
  456. && isRegExp(expect)
  457. && expect.test(value)) {
  458. continue;
  459. }
  460. if ((key in err) && isDeepEqual(value, expect, false))
  461. continue;
  462. throw new AssertionError({
  463. actual: err,
  464. expected: expected,
  465. message,
  466. operator: func.name,
  467. generatedMessage,
  468. stackStartFn: func
  469. });
  470. }
  471. return true;
  472. }
  473. if (expected.prototype !== undefined && (err instanceof expected))
  474. return true;
  475. if (Error.isPrototypeOf(expected))
  476. return false;
  477. return expected.call({}, err) === true;
  478. }
  479. /*
  480. * Comparisons
  481. */
  482. function isDeepEqual(x, y, fail) {
  483. try {
  484. return compare(x, y, null);
  485. } catch (e) {
  486. return fail;
  487. }
  488. }
  489. function compare(a, b, cache) {
  490. // Primitives.
  491. if (Object.is(a, b))
  492. return true;
  493. if (!isObject(a) || !isObject(b))
  494. return false;
  495. // Semi-primitives.
  496. if (objectString(a) !== objectString(b))
  497. return false;
  498. if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
  499. return false;
  500. if (isBuffer(a) && isBuffer(b))
  501. return a.equals(b);
  502. if (isDate(a))
  503. return Object.is(a.getTime(), b.getTime());
  504. if (isRegExp(a)) {
  505. return a.source === b.source
  506. && a.global === b.global
  507. && a.multiline === b.multiline
  508. && a.lastIndex === b.lastIndex
  509. && a.ignoreCase === b.ignoreCase;
  510. }
  511. if (isError(a)) {
  512. if (a.message !== b.message)
  513. return false;
  514. }
  515. if (isArrayBuffer(a)) {
  516. a = new Uint8Array(a);
  517. b = new Uint8Array(b);
  518. }
  519. if (isView(a) && !isBuffer(a)) {
  520. if (isBuffer(b))
  521. return false;
  522. const x = new Uint8Array(a.buffer);
  523. const y = new Uint8Array(b.buffer);
  524. if (x.length !== y.length)
  525. return false;
  526. for (let i = 0; i < x.length; i++) {
  527. if (x[i] !== y[i])
  528. return false;
  529. }
  530. return true;
  531. }
  532. if (isSet(a)) {
  533. if (a.size !== b.size)
  534. return false;
  535. const keys = new Set([...a, ...b]);
  536. return keys.size === a.size;
  537. }
  538. // Recursive.
  539. if (!cache) {
  540. cache = {
  541. a: new Map(),
  542. b: new Map(),
  543. p: 0
  544. };
  545. } else {
  546. const aa = cache.a.get(a);
  547. if (aa != null) {
  548. const bb = cache.b.get(b);
  549. if (bb != null)
  550. return aa === bb;
  551. }
  552. cache.p += 1;
  553. }
  554. cache.a.set(a, cache.p);
  555. cache.b.set(b, cache.p);
  556. const ret = recurse(a, b, cache);
  557. cache.a.delete(a);
  558. cache.b.delete(b);
  559. return ret;
  560. }
  561. function recurse(a, b, cache) {
  562. if (isMap(a)) {
  563. if (a.size !== b.size)
  564. return false;
  565. const keys = new Set([...a.keys(), ...b.keys()]);
  566. if (keys.size !== a.size)
  567. return false;
  568. for (const key of keys) {
  569. if (!compare(a.get(key), b.get(key), cache))
  570. return false;
  571. }
  572. return true;
  573. }
  574. if (isArray(a)) {
  575. if (a.length !== b.length)
  576. return false;
  577. for (let i = 0; i < a.length; i++) {
  578. if (!compare(a[i], b[i], cache))
  579. return false;
  580. }
  581. return true;
  582. }
  583. const ak = ownKeys(a);
  584. const bk = ownKeys(b);
  585. if (ak.length !== bk.length)
  586. return false;
  587. const keys = new Set([...ak, ...bk]);
  588. if (keys.size !== ak.length)
  589. return false;
  590. for (const key of keys) {
  591. if (!compare(a[key], b[key], cache))
  592. return false;
  593. }
  594. return true;
  595. }
  596. function ownKeys(obj) {
  597. const keys = Object.keys(obj);
  598. if (!Object.getOwnPropertySymbols)
  599. return keys;
  600. if (!Object.getOwnPropertyDescriptor)
  601. return keys;
  602. const symbols = Object.getOwnPropertySymbols(obj);
  603. for (const symbol of symbols) {
  604. const desc = Object.getOwnPropertyDescriptor(obj, symbol);
  605. if (desc && desc.enumerable)
  606. keys.push(symbol);
  607. }
  608. return keys;
  609. }
  610. /*
  611. * Helpers
  612. */
  613. function objectString(obj) {
  614. if (obj === undefined)
  615. return '[object Undefined]';
  616. if (obj === null)
  617. return '[object Null]';
  618. try {
  619. return Object.prototype.toString.call(obj);
  620. } catch (e) {
  621. return '[object Object]';
  622. }
  623. }
  624. function objectType(obj) {
  625. return objectString(obj).slice(8, -1);
  626. }
  627. function objectName(obj) {
  628. const type = objectType(obj);
  629. if (obj == null)
  630. return type;
  631. if (type !== 'Object' && type !== 'Error')
  632. return type;
  633. let ctor, name;
  634. try {
  635. ctor = obj.constructor;
  636. } catch (e) {
  637. ;
  638. }
  639. if (ctor == null)
  640. return type;
  641. try {
  642. name = ctor.name;
  643. } catch (e) {
  644. return type;
  645. }
  646. if (typeof name !== 'string' || name.length === 0)
  647. return type;
  648. return name;
  649. }
  650. function funcName(func) {
  651. let name;
  652. try {
  653. name = func.name;
  654. } catch (e) {
  655. ;
  656. }
  657. if (typeof name !== 'string' || name.length === 0)
  658. return 'Function';
  659. return `Function: ${name}`;
  660. }
  661. function isArray(obj) {
  662. return Array.isArray(obj);
  663. }
  664. function isArrayBuffer(obj) {
  665. return obj instanceof ArrayBuffer;
  666. }
  667. function isBuffer(obj) {
  668. return isObject(obj)
  669. && typeof obj.writeUInt32LE === 'function'
  670. && typeof obj.equals === 'function';
  671. }
  672. function isDate(obj) {
  673. return obj instanceof Date;
  674. }
  675. function isError(obj) {
  676. return obj instanceof Error;
  677. }
  678. function isMap(obj) {
  679. return obj instanceof Map;
  680. }
  681. function isObject(obj) {
  682. return obj && typeof obj === 'object';
  683. }
  684. function isPromise(obj) {
  685. return obj instanceof Promise;
  686. }
  687. function isRegExp(obj) {
  688. return obj instanceof RegExp;
  689. }
  690. function isSet(obj) {
  691. return obj instanceof Set;
  692. }
  693. function isView(obj) {
  694. return ArrayBuffer.isView(obj);
  695. }
  696. function isEncoding(enc) {
  697. if (typeof enc !== 'string')
  698. return false;
  699. switch (enc) {
  700. case 'ascii':
  701. case 'binary':
  702. case 'base64':
  703. case 'hex':
  704. case 'latin1':
  705. case 'ucs2':
  706. case 'utf8':
  707. case 'utf16le':
  708. return true;
  709. }
  710. return false;
  711. }
  712. function bufferize(actual, expected, enc) {
  713. if (typeof expected === 'string') {
  714. if (!isBuffer(actual))
  715. return null;
  716. const {constructor} = actual;
  717. if (!constructor || typeof constructor.from !== 'function')
  718. return null;
  719. if (!isEncoding(enc))
  720. return null;
  721. if (enc === 'hex' && (expected.length & 1))
  722. return null;
  723. const raw = constructor.from(expected, enc);
  724. if (enc === 'hex' && raw.length !== (expected.length >>> 1))
  725. return null;
  726. return raw;
  727. }
  728. return expected;
  729. }
  730. /*
  731. * API
  732. */
  733. assert.AssertionError = AssertionError;
  734. assert.assert = assert;
  735. assert.strict = assert;
  736. assert.ok = assert;
  737. assert.equal = equal;
  738. assert.notEqual = notEqual;
  739. assert.strictEqual = equal;
  740. assert.notStrictEqual = notEqual;
  741. assert.fail = fail;
  742. assert.throws = throws;
  743. assert.doesNotThrow = doesNotThrow;
  744. assert.rejects = rejects;
  745. assert.doesNotReject = doesNotReject;
  746. assert.ifError = ifError;
  747. assert.deepEqual = deepEqual;
  748. assert.notDeepEqual = notDeepEqual;
  749. assert.deepStrictEqual = deepEqual;
  750. assert.notDeepStrictEqual = notDeepEqual;
  751. assert.bufferEqual = bufferEqual;
  752. assert.notBufferEqual = notBufferEqual;
  753. assert.enforce = enforce;
  754. assert.range = range;
  755. /*
  756. * Expose
  757. */
  758. module.exports = assert;