1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const util = require('util'); 26 27const [, , modeArgv, sectionArgv] = process.argv; 28 29if (modeArgv === 'child') 30 child(sectionArgv); 31else 32 parent(); 33 34function parent() { 35 test('foo,tud,bar', true, 'tud'); 36 test('foo,tud', true, 'tud'); 37 test('tud,bar', true, 'tud'); 38 test('tud', true, 'tud'); 39 test('foo,bar', false, 'tud'); 40 test('', false, 'tud'); 41 42 test('###', true, '###'); 43 test('hi:)', true, 'hi:)'); 44 test('f$oo', true, 'f$oo'); 45 test('f$oo', false, 'f.oo'); 46 test('no-bar-at-all', false, 'bar'); 47 48 test('test-abc', true, 'test-abc'); 49 test('test-a', false, 'test-abc'); 50 test('test-*', true, 'test-abc'); 51 test('test-*c', true, 'test-abc'); 52 test('test-*abc', true, 'test-abc'); 53 test('abc-test', true, 'abc-test'); 54 test('a*-test', true, 'abc-test'); 55 test('*-test', true, 'abc-test'); 56} 57 58function test(environ, shouldWrite, section, forceColors = false) { 59 let expectErr = ''; 60 const expectOut = shouldWrite ? 'enabled\n' : 'disabled\n'; 61 62 const spawn = require('child_process').spawn; 63 const child = spawn(process.execPath, [__filename, 'child', section], { 64 env: Object.assign(process.env, { 65 NODE_DEBUG: environ, 66 FORCE_COLOR: forceColors ? 'true' : 'false' 67 }) 68 }); 69 70 if (shouldWrite) { 71 if (forceColors) { 72 const { colors, styles } = util.inspect; 73 const addCodes = (arr) => [`\x1B[${arr[0]}m`, `\x1B[${arr[1]}m`]; 74 const num = addCodes(colors[styles.number]); 75 const str = addCodes(colors[styles.string]); 76 const regexp = addCodes(colors[styles.regexp]); 77 const start = `${section.toUpperCase()} ${num[0]}${child.pid}${num[1]}`; 78 const debugging = `${regexp[0]}/debugging/${regexp[1]}`; 79 expectErr = 80 `${start}: this { is: ${str[0]}'a'${str[1]} } ${debugging}\n` + 81 `${start}: num=1 str=a obj={"foo":"bar"}\n`; 82 } else { 83 const start = `${section.toUpperCase()} ${child.pid}`; 84 expectErr = 85 `${start}: this { is: 'a' } /debugging/\n` + 86 `${start}: num=1 str=a obj={"foo":"bar"}\n`; 87 } 88 } 89 90 let err = ''; 91 child.stderr.setEncoding('utf8'); 92 child.stderr.on('data', (c) => { 93 err += c; 94 }); 95 96 let out = ''; 97 child.stdout.setEncoding('utf8'); 98 child.stdout.on('data', (c) => { 99 out += c; 100 }); 101 102 child.on('close', common.mustCall((c) => { 103 assert(!c); 104 assert.strictEqual(err, expectErr); 105 assert.strictEqual(out, expectOut); 106 // Run the test again, this time with colors enabled. 107 if (!forceColors) { 108 test(environ, shouldWrite, section, true); 109 } 110 })); 111} 112 113 114function child(section) { 115 const tty = require('tty'); 116 // Make sure we check for colors, no matter of the stream's default. 117 Object.defineProperty(process.stderr, 'hasColors', { 118 value: tty.WriteStream.prototype.hasColors 119 }); 120 // eslint-disable-next-line no-restricted-syntax 121 const debug = util.debuglog(section, common.mustCall((cb) => { 122 assert.strictEqual(typeof cb, 'function'); 123 })); 124 debug('this', { is: 'a' }, /debugging/); 125 debug('num=%d str=%s obj=%j', 1, 'a', { foo: 'bar' }); 126 console.log(debug.enabled ? 'enabled' : 'disabled'); 127} 128