11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci'use strict'; 231cb0ef41Sopenharmony_ciconst common = require('../common'); 241cb0ef41Sopenharmony_ciconst assert = require('assert'); 251cb0ef41Sopenharmony_ciconst util = require('util'); 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciconst { 281cb0ef41Sopenharmony_ci hijackStdout, 291cb0ef41Sopenharmony_ci hijackStderr, 301cb0ef41Sopenharmony_ci restoreStdout, 311cb0ef41Sopenharmony_ci restoreStderr 321cb0ef41Sopenharmony_ci} = require('../common/hijackstdio'); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciassert.ok(process.stdout.writable); 351cb0ef41Sopenharmony_ciassert.ok(process.stderr.writable); 361cb0ef41Sopenharmony_ci// Support legacy API 371cb0ef41Sopenharmony_ciif (common.isMainThread) { 381cb0ef41Sopenharmony_ci assert.strictEqual(typeof process.stdout.fd, 'number'); 391cb0ef41Sopenharmony_ci assert.strictEqual(typeof process.stderr.fd, 'number'); 401cb0ef41Sopenharmony_ci} 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cicommon.expectWarning( 431cb0ef41Sopenharmony_ci 'Warning', 441cb0ef41Sopenharmony_ci [ 451cb0ef41Sopenharmony_ci ['Count for \'noLabel\' does not exist'], 461cb0ef41Sopenharmony_ci ['No such label \'noLabel\' for console.timeLog()'], 471cb0ef41Sopenharmony_ci ['No such label \'noLabel\' for console.timeEnd()'], 481cb0ef41Sopenharmony_ci ['Count for \'default\' does not exist'], 491cb0ef41Sopenharmony_ci ['No such label \'default\' for console.timeLog()'], 501cb0ef41Sopenharmony_ci ['No such label \'default\' for console.timeEnd()'], 511cb0ef41Sopenharmony_ci ['Label \'default\' already exists for console.time()'], 521cb0ef41Sopenharmony_ci ['Label \'test\' already exists for console.time()'], 531cb0ef41Sopenharmony_ci ] 541cb0ef41Sopenharmony_ci); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ciconsole.countReset('noLabel'); 571cb0ef41Sopenharmony_ciconsole.timeLog('noLabel'); 581cb0ef41Sopenharmony_ciconsole.timeEnd('noLabel'); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ciconsole.time('label'); 611cb0ef41Sopenharmony_ciconsole.timeEnd('label'); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci// Test using the default label 641cb0ef41Sopenharmony_ci// on console.time(), console.countReset(), console.timeLog(), console.timeEnd() 651cb0ef41Sopenharmony_ciconsole.countReset(); 661cb0ef41Sopenharmony_ciconsole.timeLog(); 671cb0ef41Sopenharmony_ciconsole.timeEnd(); 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ciconsole.time(); 701cb0ef41Sopenharmony_ciconsole.time(); 711cb0ef41Sopenharmony_ciconsole.timeLog(); 721cb0ef41Sopenharmony_ciconsole.timeEnd(); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci// Check that the `Error` is a `TypeError` but do not check the message as it 751cb0ef41Sopenharmony_ci// will be different in different JavaScript engines. 761cb0ef41Sopenharmony_ciassert.throws(() => console.time(Symbol('test')), 771cb0ef41Sopenharmony_ci TypeError); 781cb0ef41Sopenharmony_ciassert.throws(() => console.timeEnd(Symbol('test')), 791cb0ef41Sopenharmony_ci TypeError); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci// An Object with a custom inspect function. 831cb0ef41Sopenharmony_ciconst custom_inspect = { foo: 'bar', [util.inspect.custom]: () => 'inspect' }; 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ciconst strings = []; 861cb0ef41Sopenharmony_ciconst errStrings = []; 871cb0ef41Sopenharmony_ciprocess.stdout.isTTY = false; 881cb0ef41Sopenharmony_cihijackStdout(function(data) { 891cb0ef41Sopenharmony_ci strings.push(data); 901cb0ef41Sopenharmony_ci}); 911cb0ef41Sopenharmony_ciprocess.stderr.isTTY = false; 921cb0ef41Sopenharmony_cihijackStderr(function(data) { 931cb0ef41Sopenharmony_ci errStrings.push(data); 941cb0ef41Sopenharmony_ci}); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci// Test console.log() goes to stdout 971cb0ef41Sopenharmony_ciconsole.log('foo'); 981cb0ef41Sopenharmony_ciconsole.log('foo', 'bar'); 991cb0ef41Sopenharmony_ciconsole.log('%s %s', 'foo', 'bar', 'hop'); 1001cb0ef41Sopenharmony_ciconsole.log({ slashes: '\\\\' }); 1011cb0ef41Sopenharmony_ciconsole.log(custom_inspect); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci// Test console.debug() goes to stdout 1041cb0ef41Sopenharmony_ciconsole.debug('foo'); 1051cb0ef41Sopenharmony_ciconsole.debug('foo', 'bar'); 1061cb0ef41Sopenharmony_ciconsole.debug('%s %s', 'foo', 'bar', 'hop'); 1071cb0ef41Sopenharmony_ciconsole.debug({ slashes: '\\\\' }); 1081cb0ef41Sopenharmony_ciconsole.debug(custom_inspect); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci// Test console.info() goes to stdout 1111cb0ef41Sopenharmony_ciconsole.info('foo'); 1121cb0ef41Sopenharmony_ciconsole.info('foo', 'bar'); 1131cb0ef41Sopenharmony_ciconsole.info('%s %s', 'foo', 'bar', 'hop'); 1141cb0ef41Sopenharmony_ciconsole.info({ slashes: '\\\\' }); 1151cb0ef41Sopenharmony_ciconsole.info(custom_inspect); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci// Test console.error() goes to stderr 1181cb0ef41Sopenharmony_ciconsole.error('foo'); 1191cb0ef41Sopenharmony_ciconsole.error('foo', 'bar'); 1201cb0ef41Sopenharmony_ciconsole.error('%s %s', 'foo', 'bar', 'hop'); 1211cb0ef41Sopenharmony_ciconsole.error({ slashes: '\\\\' }); 1221cb0ef41Sopenharmony_ciconsole.error(custom_inspect); 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci// Test console.warn() goes to stderr 1251cb0ef41Sopenharmony_ciconsole.warn('foo'); 1261cb0ef41Sopenharmony_ciconsole.warn('foo', 'bar'); 1271cb0ef41Sopenharmony_ciconsole.warn('%s %s', 'foo', 'bar', 'hop'); 1281cb0ef41Sopenharmony_ciconsole.warn({ slashes: '\\\\' }); 1291cb0ef41Sopenharmony_ciconsole.warn(custom_inspect); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci// test console.dir() 1321cb0ef41Sopenharmony_ciconsole.dir(custom_inspect); 1331cb0ef41Sopenharmony_ciconsole.dir(custom_inspect, { showHidden: false }); 1341cb0ef41Sopenharmony_ciconsole.dir({ foo: { bar: { baz: true } } }, { depth: 0 }); 1351cb0ef41Sopenharmony_ciconsole.dir({ foo: { bar: { baz: true } } }, { depth: 1 }); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci// Test console.dirxml() 1381cb0ef41Sopenharmony_ciconsole.dirxml(custom_inspect, custom_inspect); 1391cb0ef41Sopenharmony_ciconsole.dirxml( 1401cb0ef41Sopenharmony_ci { foo: { bar: { baz: true } } }, 1411cb0ef41Sopenharmony_ci { foo: { bar: { quux: false } } }, 1421cb0ef41Sopenharmony_ci { foo: { bar: { quux: true } } } 1431cb0ef41Sopenharmony_ci); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci// Test console.trace() 1461cb0ef41Sopenharmony_ciconsole.trace('This is a %j %d', { formatted: 'trace' }, 10, 'foo'); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci// Test console.time() and console.timeEnd() output 1491cb0ef41Sopenharmony_ciconsole.time('label'); 1501cb0ef41Sopenharmony_ciconsole.timeEnd('label'); 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci// Verify that Object.prototype properties can be used as labels 1531cb0ef41Sopenharmony_ciconsole.time('__proto__'); 1541cb0ef41Sopenharmony_ciconsole.timeEnd('__proto__'); 1551cb0ef41Sopenharmony_ciconsole.time('constructor'); 1561cb0ef41Sopenharmony_ciconsole.timeEnd('constructor'); 1571cb0ef41Sopenharmony_ciconsole.time('hasOwnProperty'); 1581cb0ef41Sopenharmony_ciconsole.timeEnd('hasOwnProperty'); 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci// Verify that values are coerced to strings. 1611cb0ef41Sopenharmony_ciconsole.time([]); 1621cb0ef41Sopenharmony_ciconsole.timeEnd([]); 1631cb0ef41Sopenharmony_ciconsole.time({}); 1641cb0ef41Sopenharmony_ciconsole.timeEnd({}); 1651cb0ef41Sopenharmony_ci// Repeat the object call to verify that everything really worked. 1661cb0ef41Sopenharmony_ciconsole.time({}); 1671cb0ef41Sopenharmony_ciconsole.timeEnd({}); 1681cb0ef41Sopenharmony_ciconsole.time(null); 1691cb0ef41Sopenharmony_ciconsole.timeEnd(null); 1701cb0ef41Sopenharmony_ciconsole.time(undefined); 1711cb0ef41Sopenharmony_ciconsole.timeEnd('default'); 1721cb0ef41Sopenharmony_ciconsole.time('default'); 1731cb0ef41Sopenharmony_ciconsole.timeEnd(); 1741cb0ef41Sopenharmony_ciconsole.time(NaN); 1751cb0ef41Sopenharmony_ciconsole.timeEnd(NaN); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci// Make sure calling time twice without timeEnd doesn't reset the timer. 1781cb0ef41Sopenharmony_ciconsole.time('test'); 1791cb0ef41Sopenharmony_ciconst time = console._times.get('test'); 1801cb0ef41Sopenharmony_cisetTimeout(() => { 1811cb0ef41Sopenharmony_ci console.time('test'); 1821cb0ef41Sopenharmony_ci assert.deepStrictEqual(console._times.get('test'), time); 1831cb0ef41Sopenharmony_ci console.timeEnd('test'); 1841cb0ef41Sopenharmony_ci}, 1); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ciconsole.time('log1'); 1871cb0ef41Sopenharmony_ciconsole.timeLog('log1'); 1881cb0ef41Sopenharmony_ciconsole.timeLog('log1', 'test'); 1891cb0ef41Sopenharmony_ciconsole.timeLog('log1', {}, [1, 2, 3]); 1901cb0ef41Sopenharmony_ciconsole.timeEnd('log1'); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ciconsole.assert(false, '%s should', 'console.assert', 'not throw'); 1931cb0ef41Sopenharmony_ciassert.strictEqual(errStrings[errStrings.length - 1], 1941cb0ef41Sopenharmony_ci 'Assertion failed: console.assert should not throw\n'); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ciconsole.assert(false); 1971cb0ef41Sopenharmony_ciassert.strictEqual(errStrings[errStrings.length - 1], 'Assertion failed\n'); 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ciconsole.assert(true, 'this should not throw'); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciconsole.assert(true); 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ciassert.strictEqual(strings.length, process.stdout.writeTimes); 2041cb0ef41Sopenharmony_ciassert.strictEqual(errStrings.length, process.stderr.writeTimes); 2051cb0ef41Sopenharmony_cirestoreStdout(); 2061cb0ef41Sopenharmony_cirestoreStderr(); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci// Verify that console.timeEnd() doesn't leave dead links 2091cb0ef41Sopenharmony_ciconst timesMapSize = console._times.size; 2101cb0ef41Sopenharmony_ciconsole.time('label1'); 2111cb0ef41Sopenharmony_ciconsole.time('label2'); 2121cb0ef41Sopenharmony_ciconsole.time('label3'); 2131cb0ef41Sopenharmony_ciconsole.timeEnd('label1'); 2141cb0ef41Sopenharmony_ciconsole.timeEnd('label2'); 2151cb0ef41Sopenharmony_ciconsole.timeEnd('label3'); 2161cb0ef41Sopenharmony_ciassert.strictEqual(console._times.size, timesMapSize); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ciconst expectedStrings = [ 2191cb0ef41Sopenharmony_ci 'foo', 'foo bar', 'foo bar hop', "{ slashes: '\\\\\\\\' }", 'inspect', 2201cb0ef41Sopenharmony_ci]; 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_cifor (const expected of expectedStrings) { 2231cb0ef41Sopenharmony_ci assert.strictEqual(strings.shift(), `${expected}\n`); 2241cb0ef41Sopenharmony_ci assert.strictEqual(errStrings.shift(), `${expected}\n`); 2251cb0ef41Sopenharmony_ci} 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_cifor (const expected of expectedStrings) { 2281cb0ef41Sopenharmony_ci assert.strictEqual(strings.shift(), `${expected}\n`); 2291cb0ef41Sopenharmony_ci assert.strictEqual(errStrings.shift(), `${expected}\n`); 2301cb0ef41Sopenharmony_ci} 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_cifor (const expected of expectedStrings) { 2331cb0ef41Sopenharmony_ci assert.strictEqual(strings.shift(), `${expected}\n`); 2341cb0ef41Sopenharmony_ci} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciassert.strictEqual(strings.shift(), 2371cb0ef41Sopenharmony_ci "{\n foo: 'bar',\n [Symbol(nodejs.util.inspect.custom)]:" + 2381cb0ef41Sopenharmony_ci ' [Function: [nodejs.util.inspect.custom]]\n}\n'); 2391cb0ef41Sopenharmony_ciassert.strictEqual(strings.shift(), 2401cb0ef41Sopenharmony_ci "{\n foo: 'bar',\n [Symbol(nodejs.util.inspect.custom)]:" + 2411cb0ef41Sopenharmony_ci ' [Function: [nodejs.util.inspect.custom]]\n}\n'); 2421cb0ef41Sopenharmony_ciassert.ok(strings.shift().includes('foo: [Object]')); 2431cb0ef41Sopenharmony_ciassert.strictEqual(strings.shift().includes('baz'), false); 2441cb0ef41Sopenharmony_ciassert.strictEqual(strings.shift(), 'inspect inspect\n'); 2451cb0ef41Sopenharmony_ciassert.ok(strings[0].includes('foo: { bar: { baz:')); 2461cb0ef41Sopenharmony_ciassert.ok(strings[0].includes('quux')); 2471cb0ef41Sopenharmony_ciassert.ok(strings.shift().includes('quux: true')); 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^label: \d+(\.\d{1,3})?(ms|s)$/); 2501cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^__proto__: \d+(\.\d{1,3})?(ms|s)$/); 2511cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^constructor: \d+(\.\d{1,3})?(ms|s)$/); 2521cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^hasOwnProperty: \d+(\.\d{1,3})?(ms|s)$/); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci// Verify that console.time() coerces label values to strings as expected 2551cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^: \d+(\.\d{1,3})?(ms|s)$/); 2561cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), 2571cb0ef41Sopenharmony_ci /^\[object Object\]: \d+(\.\d{1,3})?(ms|s)$/); 2581cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), 2591cb0ef41Sopenharmony_ci /^\[object Object\]: \d+(\.\d{1,3})?(ms|s)$/); 2601cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^null: \d+(\.\d{1,3})?(ms|s)$/); 2611cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^default: \d+(\.\d{1,3})?(ms|s)$/); 2621cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^default: \d+(\.\d{1,3})?(ms|s)$/); 2631cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^NaN: \d+(\.\d{1,3})?(ms|s)$/); 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^log1: \d+(\.\d{1,3})?(ms|s)$/); 2661cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^log1: \d+(\.\d{1,3})?(ms|s) test$/); 2671cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), 2681cb0ef41Sopenharmony_ci /^log1: \d+(\.\d{1,3})?(ms|s) {} \[ 1, 2, 3 ]$/); 2691cb0ef41Sopenharmony_ciassert.match(strings.shift().trim(), /^log1: \d+(\.\d{1,3})?(ms|s)$/); 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci// Make sure that we checked all strings 2721cb0ef41Sopenharmony_ciassert.strictEqual(strings.length, 0); 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ciassert.strictEqual(errStrings.shift().split('\n').shift(), 2751cb0ef41Sopenharmony_ci 'Trace: This is a {"formatted":"trace"} 10 foo'); 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci// Hijack stderr to catch `process.emitWarning` which is using 2781cb0ef41Sopenharmony_ci// `process.nextTick` 2791cb0ef41Sopenharmony_cihijackStderr(common.mustCall(function(data) { 2801cb0ef41Sopenharmony_ci restoreStderr(); 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci // stderr.write will catch sync error, so use `process.nextTick` here 2831cb0ef41Sopenharmony_ci process.nextTick(function() { 2841cb0ef41Sopenharmony_ci assert.strictEqual(data.includes('noLabel'), true); 2851cb0ef41Sopenharmony_ci }); 2861cb0ef41Sopenharmony_ci})); 287