Skip to content

Commit 2e6dd93

Browse files
committed
assert: fix diff color output
The color output was broken at some point and that was not detected because it was not tested for properly so far. This makes sure the colors work again and it adds a regression test as well. PR-URL: #19464 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent d74919c commit 2e6dd93

File tree

4 files changed

+74
-59
lines changed

4 files changed

+74
-59
lines changed

lib/internal/errors.js

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ const kInfo = Symbol('info');
1515
const messages = new Map();
1616
const codes = {};
1717

18-
var green = '';
19-
var red = '';
20-
var white = '';
18+
let green = '';
19+
let red = '';
20+
let white = '';
2121

2222
const {
2323
errmap,
@@ -29,16 +29,9 @@ const { kMaxLength } = process.binding('buffer');
2929
const { defineProperty } = Object;
3030

3131
// Lazily loaded
32-
var util_ = null;
32+
var util;
3333
var buffer;
3434

35-
function lazyUtil() {
36-
if (!util_) {
37-
util_ = require('util');
38-
}
39-
return util_;
40-
}
41-
4235
var internalUtil = null;
4336
function lazyInternalUtil() {
4437
if (!internalUtil) {
@@ -47,6 +40,13 @@ function lazyInternalUtil() {
4740
return internalUtil;
4841
}
4942

43+
function inspectValue(val) {
44+
return util.inspect(
45+
val,
46+
{ compact: false, customInspect: false }
47+
).split('\n');
48+
}
49+
5050
function makeNodeError(Base) {
5151
return class NodeError extends Base {
5252
constructor(key, ...args) {
@@ -210,11 +210,9 @@ function createErrDiff(actual, expected, operator) {
210210
var lastPos = 0;
211211
var end = '';
212212
var skipped = false;
213-
const util = lazyUtil();
214-
const actualLines = util
215-
.inspect(actual, { compact: false, customInspect: false }).split('\n');
216-
const expectedLines = util
217-
.inspect(expected, { compact: false, customInspect: false }).split('\n');
213+
if (util === undefined) util = require('util');
214+
const actualLines = inspectValue(actual);
215+
const expectedLines = inspectValue(expected);
218216
const msg = `Input A expected to ${operator} input B:\n` +
219217
`${green}+ expected${white} ${red}- actual${white}`;
220218
const skippedMsg = ' ... Lines skipped';
@@ -333,14 +331,20 @@ class AssertionError extends Error {
333331
if (message != null) {
334332
super(message);
335333
} else {
336-
if (util_ === null &&
337-
process.stdout.isTTY &&
338-
process.stdout.getColorDepth() !== 1) {
339-
green = '\u001b[32m';
340-
white = '\u001b[39m';
341-
red = '\u001b[31m';
334+
if (process.stdout.isTTY) {
335+
// Reset on each call to make sure we handle dynamically set environment
336+
// variables correct.
337+
if (process.stdout.getColorDepth() !== 1) {
338+
green = '\u001b[32m';
339+
white = '\u001b[39m';
340+
red = '\u001b[31m';
341+
} else {
342+
green = '';
343+
white = '';
344+
red = '';
345+
}
342346
}
343-
const util = lazyUtil();
347+
if (util === undefined) util = require('util');
344348
if (typeof actual === 'object' && actual !== null &&
345349
'stack' in actual && actual instanceof Error) {
346350
actual = `${actual.name}: ${actual.message}`;
@@ -361,10 +365,7 @@ class AssertionError extends Error {
361365
} else if (errorDiff === 1) {
362366
// In case the objects are equal but the operator requires unequal, show
363367
// the first object and say A equals B
364-
const res = util.inspect(
365-
actual,
366-
{ compact: false, customInspect: false }
367-
).split('\n');
368+
const res = inspectValue(actual);
368369

369370
if (res.length > 20) {
370371
res[19] = '...';
@@ -406,10 +407,10 @@ function message(key, args) {
406407
const msg = messages.get(key);
407408
internalAssert(msg, `An invalid error message key was used: ${key}.`);
408409
let fmt;
410+
if (util === undefined) util = require('util');
409411
if (typeof msg === 'function') {
410412
fmt = msg;
411413
} else {
412-
const util = lazyUtil();
413414
fmt = util.format;
414415
if (args === undefined || args.length === 0)
415416
return msg;
@@ -479,7 +480,8 @@ function errnoException(err, syscall, original) {
479480
// getSystemErrorName(err) to guard against invalid arguments from users.
480481
// This can be replaced with [ code ] = errmap.get(err) when this method
481482
// is no longer exposed to user land.
482-
const code = lazyUtil().getSystemErrorName(err);
483+
if (util === undefined) util = require('util');
484+
const code = util.getSystemErrorName(err);
483485
const message = original ?
484486
`${syscall} ${code} ${original}` : `${syscall} ${code}`;
485487

@@ -508,7 +510,8 @@ function exceptionWithHostPort(err, syscall, address, port, additional) {
508510
// getSystemErrorName(err) to guard against invalid arguments from users.
509511
// This can be replaced with [ code ] = errmap.get(err) when this method
510512
// is no longer exposed to user land.
511-
const code = lazyUtil().getSystemErrorName(err);
513+
if (util === undefined) util = require('util');
514+
const code = util.getSystemErrorName(err);
512515
let details = '';
513516
if (port && port > 0) {
514517
details = ` ${address}:${port}`;
@@ -768,10 +771,9 @@ E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected', Error);
768771
E('ERR_INVALID_ADDRESS_FAMILY', 'Invalid address family: %s', RangeError);
769772
E('ERR_INVALID_ARG_TYPE', invalidArgType, TypeError);
770773
E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => {
771-
const util = lazyUtil();
772774
let inspected = util.inspect(value);
773775
if (inspected.length > 128) {
774-
inspected = inspected.slice(0, 128) + '...';
776+
inspected = `${inspected.slice(0, 128)}...`;
775777
}
776778
return `The argument '${name}' ${reason}. Received ${inspected}`;
777779
}, TypeError, RangeError);

test/parallel/test-assert.js

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,8 @@ const { writeFileSync, unlinkSync } = require('fs');
3434
const { inspect } = require('util');
3535
const a = assert;
3636

37-
const colors = process.stdout.isTTY && process.stdout.getColorDepth() > 1;
3837
const start = 'Input A expected to deepStrictEqual input B:';
39-
const actExp = colors ?
40-
'\u001b[32m+ expected\u001b[39m \u001b[31m- actual\u001b[39m' :
41-
'+ expected - actual';
38+
const actExp = '+ expected - actual';
4239

4340
assert.ok(a.AssertionError.prototype instanceof Error,
4441
'a.AssertionError instanceof Error');
@@ -442,8 +439,6 @@ common.expectsError(
442439
Error.stackTraceLimit = tmpLimit;
443440

444441
// Test error diffs.
445-
const plus = colors ? '\u001b[32m+\u001b[39m' : '+';
446-
const minus = colors ? '\u001b[31m-\u001b[39m' : '-';
447442
let message = [
448443
start,
449444
`${actExp} ... Lines skipped`,
@@ -452,8 +447,8 @@ common.expectsError(
452447
' [',
453448
'...',
454449
' 2,',
455-
`${minus} 3`,
456-
`${plus} '3'`,
450+
'- 3',
451+
"+ '3'",
457452
' ]',
458453
'...',
459454
' 5',
@@ -470,7 +465,7 @@ common.expectsError(
470465
' 1,',
471466
'...',
472467
' 0,',
473-
`${plus} 1,`,
468+
'+ 1,',
474469
' 1,',
475470
'...',
476471
' 1',
@@ -490,7 +485,7 @@ common.expectsError(
490485
' 1,',
491486
'...',
492487
' 0,',
493-
`${minus} 1,`,
488+
'- 1,',
494489
' 1,',
495490
'...',
496491
' 1',
@@ -508,12 +503,12 @@ common.expectsError(
508503
'',
509504
' [',
510505
' 1,',
511-
`${minus} 2,`,
512-
`${plus} 1,`,
506+
'- 2,',
507+
'+ 1,',
513508
' 1,',
514509
' 1,',
515510
' 0,',
516-
`${minus} 1,`,
511+
'- 1,',
517512
' 1',
518513
' ]'
519514
].join('\n');
@@ -527,12 +522,12 @@ common.expectsError(
527522
start,
528523
actExp,
529524
'',
530-
`${minus} [`,
531-
`${minus} 1,`,
532-
`${minus} 2,`,
533-
`${minus} 1`,
534-
`${minus} ]`,
535-
`${plus} undefined`,
525+
'- [',
526+
'- 1,',
527+
'- 2,',
528+
'- 1',
529+
'- ]',
530+
'+ undefined',
536531
].join('\n');
537532
assert.throws(
538533
() => assert.deepEqual([1, 2, 1]),
@@ -543,7 +538,7 @@ common.expectsError(
543538
actExp,
544539
'',
545540
' [',
546-
`${minus} 1,`,
541+
'- 1,',
547542
' 2,',
548543
' 1',
549544
' ]'
@@ -556,9 +551,9 @@ common.expectsError(
556551
`${actExp} ... Lines skipped\n` +
557552
'\n' +
558553
' [\n' +
559-
`${minus} 1,\n`.repeat(10) +
554+
'- 1,\n'.repeat(10) +
560555
'...\n' +
561-
`${plus} 2,\n`.repeat(10) +
556+
'+ 2,\n'.repeat(10) +
562557
'...';
563558
assert.throws(
564559
() => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)),
@@ -572,11 +567,11 @@ common.expectsError(
572567
message: `${start}\n` +
573568
`${actExp}\n` +
574569
'\n' +
575-
`${minus} {}\n` +
576-
`${plus} {\n` +
577-
`${plus} loop: 'forever',\n` +
578-
`${plus} [Symbol(util.inspect.custom)]: [Function]\n` +
579-
`${plus} }`
570+
'- {}\n' +
571+
'+ {\n' +
572+
"+ loop: 'forever',\n" +
573+
'+ [Symbol(util.inspect.custom)]: [Function]\n' +
574+
'+ }'
580575
});
581576

582577
// notDeepEqual tests

test/pseudo-tty/test-assert-colors.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert').strict;
4+
5+
try {
6+
// Activate colors even if the tty does not support colors.
7+
process.env.COLORTERM = '1';
8+
assert.deepStrictEqual([1, 2], [2, 2]);
9+
} catch (err) {
10+
const expected = 'Input A expected to deepStrictEqual input B:\n' +
11+
'\u001b[32m+ expected\u001b[39m \u001b[31m- actual\u001b[39m\n\n' +
12+
' [\n' +
13+
'\u001b[31m-\u001b[39m 1,\n' +
14+
'\u001b[32m+\u001b[39m 2,\n' +
15+
' 2\n' +
16+
' ]';
17+
assert.strictEqual(err.message, expected);
18+
}

test/pseudo-tty/test-assert-colors.out

Whitespace-only changes.

0 commit comments

Comments
 (0)