diff --git a/lib/jobs/list_core.js b/lib/jobs/list_core.js new file mode 100644 index 0000000..6cd69ee --- /dev/null +++ b/lib/jobs/list_core.js @@ -0,0 +1,188 @@ +'use strict'; + +const os = require('os'); +const fs = require('fs'); +const fsx = require('fs').promises; +const path = require('path'); +const utils = require('../utils'); + +const REPORT_INTERVAL = 60 * 1000; + +// if user renamed core file, then only check those with the +// prefix +function check(prefixList, item) { + return prefixList.some((prefix) => { + return item.startsWith(prefix) && !item.endsWith('.gz'); + }); +} + +class ListCoreJob { + /** + * 在以下3种路径下查找core文件 + * 1. 用户指定路径 config.json里面 coredir:[dir1, dir2, ...] + * 2. 用户在 /proc/sys/kernel/core_pattern 指定core生成格式 + * /proc/sys/kernel/core_pattern 可以设置格式化的 core 文件保存位置或文件名 + * echo “/opt/corefile/core-%e-%p-%t” > /proc/sys/kernel/core_pattern + * 将会控制所产生的 core 文件会存放到 /corefile + * 以下是参数列表 : + * %p - insert pid into filename + * %u - insert current uid into filename + * %g - insert current gid into filename + * %s - insert signal that caused the coredump into the filename + * %t - insert UNIX time that the coredump occurred into filename + * %h - insert hostname where the coredump happened into filename + * %e - insert coredumping executable name into filename + * 注: 只处理上面这种形式,对于第三方处理的情况不考虑 + * 3. 那么对于linux系统,在Node进程的pwd目录,对于Mac在/cores下查找 + */ + constructor(config) { + this.coreFileNamePrefix = ['core']; + + if (config && config.coredir) { + if (Array.isArray(config.coredir)) { + this.coredir = config.coredir; + } else if (typeof config.coredir === 'string') { + this.coredir = [config.coredir]; + } else { + // ignore other types + this.coredir = []; + } + } else { + this.coredir = []; + } + + // for linux, check + // core dir specified by /proc/sys/kernal/core_pattern e.g. '/tmp/core_%e.%p' + if (os.platform() === 'linux') { + if (!fs.existsSync('/proc/sys/kernel/core_pattern')) { + return; + } + + const patt = fs.readFileSync('/proc/sys/kernel/core_pattern', 'utf8').trim().split(' ')[0]; + if (patt.indexOf('%') > 0) { + // /tmp/core_%e.%p + const coredir_ = path.parse(patt).dir; + if (fs.existsSync(coredir_)) { + try { + fs.accessSync(coredir_, fs.R_OK); + this.coredir.push(coredir_); + const prefix = path.parse(patt).name.split('%')[0]; + if (prefix !== this.coreFileNamePrefix[0]) { + this.coreFileNamePrefix.push(prefix); + } + } catch (e) { + console.log(coredir_ + ' is unaccessible: ' + e.message); + } + } + } + } + } + + async getNodePids() { + const { stdout } = await utils.execAsync('ps -e -o pid,args | grep -E "node " | grep -v grep'); + const pids = []; + const processes = stdout.toString().trim().split('\n'); + for (let i = 0; i < processes.length; i++) { + if (processes[i] && processes[i].split(' ')[0]) { + pids.push(processes[i].split(' ')[0]); + } + } + return pids; + } + + async getNodePWD(pid) { + const path = `/proc/${pid}/environ`; + try { + await fsx.access(path, fs.constants.R_OK); + } catch (err) { + // 忽略该进程 + return null; + } + + const env = await fsx.readFile(path, 'utf8'); + const envs = env.toString().trim().split('\u0000'); + for (let i = 0; i < envs.length; i++) { + if (envs[i].indexOf('PWD') === 0) { + return envs[i].split('=')[1]; + } + } + + return null; + } + + async findCores(dir) { + const results = []; + try { + await fsx.access(dir); + } catch (ex) { + return results; + } + + const files = await fsx.readdir(dir); + for (let i = 0; i < files.length; i++) { + if (!check(this.coreFileNamePrefix, files[i])) { + continue; + } + const file = path.join(dir, files[i]); + const stat = await fsx.stat(file); + // bypass directory + if (!stat.isFile()) { + continue; + } + + // bypass core created before agentx startup + if (stat.ctimeMs < Date.now() - REPORT_INTERVAL) { + continue; + } + + results.push({ + path: file, + size: stat.size, + ctime: stat.ctime + }); + } + + return results; + } + + async run() { + // 非 linux,不处理,不上报 + if (os.platform() !== 'linux') { + return null; + } + + // 查找当前运行中的 Node 进程 pid 列表 + const pids = await this.getNodePids(); + const pwds = []; + for (let i = 0; i < pids.length; i++) { + // 根据进程 ID,获取进程的 PWD 目录 + const pwd = await this.getNodePWD(pids[i]); + if (pwd) { + pwds.push(pwd); + } + } + // 合并目录并去重 + const dirs = Array.from(new Set([...this.coredir, ...pwds])); + if (dirs.length === 0) { + return null; + } + + // 从目录中查找符合条件的 core 文件列表 + let cores = []; + const count = dirs.length; + for (let i = 0; i < count; i++) { + const dir = dirs[i]; + const list = await this.findCores(dir); + cores = [...cores, ...list]; + } + + return { + type: 'coredump', + metrics: cores + }; + } + + static reportInterval = REPORT_INTERVAL; // 1 min +} + +module.exports = ListCoreJob; diff --git a/lib/orders/list_core.js b/lib/orders/list_core.js deleted file mode 100644 index 074552b..0000000 --- a/lib/orders/list_core.js +++ /dev/null @@ -1,241 +0,0 @@ -'use strict'; - -const os = require('os'); -const fs = require('fs'); -const path = require('path'); -const exec = require('child_process').exec; - -exports.coredir = []; -const REPORT_INTERVAL = 60 * 1000; - -// if user renamed core file, then only check those with the -// prefix -let coreFileNamePrefix = ['core']; - -const statFile = function (filepath, callback) { - fs.stat(filepath, function (err, stat) { - if (err) { - return callback(err); - } - - // bypass directory - if (!stat.isFile()) { - return callback(null, null); - } - - // bypass core created before agentx startup - if (stat.ctimeMs < Date.now() - REPORT_INTERVAL) { - return callback(null, null); - } - - return callback(null, { - path: filepath, - size: stat.size, - ctime: stat.ctime - }); - }); -}; - -function check(prefixList, item) { - return prefixList.some((prefix) => { - return item.startsWith(prefix) && !item.endsWith('.gz'); - }); -} - -const statDir = function (dir, callback) { - fs.readdir(dir, function (err, files) { - if (err) { - return callback(err); - } - let finished = 0; - const count = files.length; - const list = []; - //the empty dir callback directly - if (count === 0) { - callback(null, list); - return; - } - const done = function (err, stat) { - finished++; - if (stat) { - list.push(stat); - } - if (finished === count) { - callback(err, list); - } - }; - - for (let i = 0; i < count; i++) { - if (check(coreFileNamePrefix, files[i])) { - const file = path.join(dir, files[i]); - statFile(file, done); - } else { - done(); - } - } - }); -}; - -const statCores = function (coredirs, callback) { - const corelist = { ok: true, data: [] }; - const count = coredirs.length; - let finished = 0; - const done = function (err, stat) { - finished++; - if (!err) { - corelist.data = corelist.data.concat(stat); - } - if (finished === count) { - callback(err, corelist); - } - }; - - for (let i = 0; i < count; i++) { - const dir = coredirs[i]; - statDir(dir, done); - } -}; - -const getNodePWD = function (pid, callback) { - exec('cat /proc/' + pid + '/environ', function (err, env) { - if (err) { - // 忽略该进程 - return callback(null, null); - } - const envs = env.toString().trim().split('\u0000'); - for (let i = 0; i < envs.length; i++) { - if (envs[i].indexOf('PWD') === 0) { - return callback(null, envs[i].split('=')[1]); - } - } - return callback(null, null); - }); -}; - -const getNodePids = function (callback) { - exec('ps -e -o pid,args | grep -E "node " | grep -v grep', function (err, nodes) { - if (err) { - return callback(err); - } - const pids = []; - const processes = nodes.toString().trim().split('\n'); - for (let i = 0; i < processes.length; i++) { - if (processes[i] && processes[i].split(' ')[0]) { - pids.push(processes[i].split(' ')[0]); - } - } - callback(null, pids); - }); -}; - -const getNodePWDs = function (callback) { - getNodePids(function (err, pids) { - if (err) { - return callback(err); - } - - let finished = 0; - const count = pids.length; - if (count === 0) { - callback(null, []); - } - const pwds = []; - const done = function (err, pwd) { - finished++; - if (pwd && pwds.indexOf(pwd) === -1) { - pwds.push(pwd); - } - if (finished === count) { - callback(err, pwds); - } - }; - - for (let i = 0; i < count; i++) { - getNodePWD(pids[i], done); - } - }); -}; - -/******************************************************************************* -* 在以下3种路径下查找core文件 -* 1. 用户指定路径 config.json里面 coredir:[dir1, dir2, ...] -* 2. 用户在 /proc/sys/kernel/core_pattern 指定core生成格式 -* /proc/sys/kernel/core_pattern 可以设置格式化的 core 文件保存位置或文件名 -* echo “/opt/corefile/core-%e-%p-%t” > /proc/sys/kernel/core_pattern -* 将会控制所产生的 core 文件会存放到 /corefile -* 以下是参数列表 : -* %p - insert pid into filename -* %u - insert current uid into filename -* %g - insert current gid into filename -* %s - insert signal that caused the coredump into the filename -* %t - insert UNIX time that the coredump occurred into filename -* %h - insert hostname where the coredump happened into filename -* %e - insert coredumping executable name into filename -* 注: 只处理上面这种形式,对于第三方处理的情况不考虑 -* 3. 那么对于linux系统,在Node进程的pwd目录,对于Mac在/cores下查找 -* -*******************************************************************************/ - -exports.init = function (config) { - exports.coredir = []; - coreFileNamePrefix = ['core']; - - if (config && config.coredir) { - if (Array.isArray(config.coredir)) { - exports.coredir = config.coredir; - } else if (typeof config.coredir === 'string') { - exports.coredir = [config.coredir]; - } - } - - // for linux, check - // core dir specified by /proc/sys/kernal/core_pattern e.g. '/tmp/core_%e.%p' - if (os.platform() === 'linux') { - if (!fs.existsSync('/proc/sys/kernel/core_pattern')) { return; } - const patt = fs.readFileSync('/proc/sys/kernel/core_pattern', 'utf8').trim().split(' ')[0]; - if (patt.indexOf('%') > 0) { - // /tmp/core_%e.%p - const coredir_ = path.parse(patt).dir; - if (fs.existsSync(coredir_)) { - try { - fs.accessSync(coredir_, fs.R_OK); - exports.coredir.push(coredir_); - const prefix = path.parse(patt).name.split('%')[0]; - if (prefix !== coreFileNamePrefix[0]) { - coreFileNamePrefix.push(prefix); - } - } catch (e) { - console.log(coredir_ + ' is unaccessible: ' + e.message); - } - } - } - return; - } -}; - -exports.run = function (callback) { - const result = { type: 'coredump', metrics: null }; - if (os.platform() !== 'linux') { - return callback(null, result); - } - - getNodePWDs(function (err, pwds) { - if (err) { - return callback(err); - } - let dirs = exports.coredir.concat(pwds); - if (!Array.isArray(dirs) || dirs.length === 0) { - return callback(null, result); - } - dirs = Array.from(new Set(dirs)); - statCores(dirs, function (err, cores) { - if (err) { - callback(err); - } - result.metrics = cores; - callback(null, result); - }); - }); -}; - -exports.reportInterval = REPORT_INTERVAL; // 1 min diff --git a/lib/utils.js b/lib/utils.js index b1ac8dc..e26e03c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -4,10 +4,13 @@ const os = require('os'); const fs = require('fs'); const crypto = require('crypto'); const execFile = require('child_process').execFile; +const exec = require('child_process').exec; + const util = require('util'); const accessAsync = util.promisify(fs.access); const execFileAsync = util.promisify(execFile); +const execAsync = util.promisify(exec); exports.sha1 = function (str, key) { return crypto.createHmac('sha1', key).update(str).digest('hex'); @@ -36,6 +39,8 @@ exports.execFileAsync = async function (command, args = []) { return await execFileAsync(command, args); }; +exports.execAsync = execAsync; + let uid = 1000; exports.uid = function () { return uid++; diff --git a/package.json b/package.json index a6599fa..4c65f8a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "lint": "eslint --fix .", "test-dev": "mocha -t 5000 -R spec", "cov-dev": "nyc --reporter=html --reporter=text --reporter=lcov npm run test-dev", - "test": "mocha --exit -b -t 5000 -R spec test/**/*.test.js test/*.test.js", + "test": "mocha --exit -t 5000 -R spec test/**/*.test.js test/*.test.js", "cov": "nyc --reporter=html --reporter=text --reporter=lcov npm run test", "ci": "npm run lint && npm run cov && codecov", "ut": "mocha -t 5000 -R spec" diff --git a/test/jobs/list_core.test.js b/test/jobs/list_core.test.js new file mode 100644 index 0000000..a6e4b6d --- /dev/null +++ b/test/jobs/list_core.test.js @@ -0,0 +1,285 @@ +'use strict'; + +const mm = require('mm'); +const fs = require('fs'); +const path = require('path'); +const expect = require('expect.js'); +const ListCoreJob = require('../../lib/jobs/list_core'); +const assert = require('assert'); + +describe('constructor', function () { + it('should ok', async function () { + const job = new ListCoreJob({ coredir: [] }); + assert.deepStrictEqual(job.coredir, []); + }); + + it('coredir is string should ok', async function () { + const job = new ListCoreJob({ coredir: '/tmp' }); + assert.deepStrictEqual(job.coredir, ['/tmp']); + }); + + it('ignore coredir is number should ok', async function () { + const job = new ListCoreJob({ coredir: 1 }); + assert.deepStrictEqual(job.coredir, []); + }); +}); + +describe('mock non-linux', function () { + before(function () { + mm.data(require('os'), 'platform', 'darwin'); + }); + + after(function () { + mm.restore(); + }); + + it('no coredirs', async function () { + const job = new ListCoreJob({ coredir: [] }); + const params = await job.run(); + expect(params).to.be(null); + }); +}); + +describe('mock linux', function () { + + describe('core created before agentx startup will not reported', function () { + const mock = { + isFile: function () { return true; }, + dev: 2053, + mode: 16893, + nlink: 2, + uid: 1000, + gid: 1000, + rdev: 0, + blksize: 4096, + ino: 2367914, + size: 4096, + blocks: 8, + atimeMs: 1522831557878.927, + mtimeMs: 1522831557778.928 - 70000, + ctimeMs: 1522831557778.928 - 70000, + birthtimeMs: 1522831557778.928, + atime: '2018-04-04T08:45:57.879Z', + mtime: '2018-04-04T08:45:57.779Z', + ctime: '2018-04-04T08:45:57.779Z', + birthtime: '2018-04-04T08:45:57.779Z' + }; + + const dir = path.join(__dirname, '../logdir'); + const corePath = path.join(dir, 'core.123'); + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + mm.data(require('fs'), 'stat', mock); + fs.writeFileSync(corePath, ''); + }); + + after(function () { + mm.restore(); + fs.unlinkSync(corePath); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ + coredir: [dir] + }); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(1); + }); + }); + + describe('coredir not specified', function () { + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + }); + + after(function () { + mm.restore(); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ coredir: [] }); + const params = await job.run(); + expect(params).to.be(null); + }); + }); + + describe('when specify the coredir', function () { + const dir = path.join(__dirname, '../logdir'); + const corePath = path.join(dir, 'core.123'); + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + fs.writeFileSync(corePath, ''); + }); + + after(function () { + mm.restore(); + fs.unlinkSync(corePath); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ coredir: [dir] }); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(1); + expect(params.metrics[0].path).to.be(corePath); + }); + }); + + describe('when coredir not exists', function () { + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + }); + + after(function () { + mm.restore(); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ + coredir: [path.join(__dirname, '../non-logdir')] + }); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(0); + }); + }); + + describe('when coredir is empty', function () { + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + }); + + after(function () { + mm.restore(); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ + coredir: [ + path.join(__dirname, '../logdir/empty') + ] + }); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(0); + }); + }); + + describe('when duplicate dir configured', function () { + const dir = path.join(__dirname, '../logdir'); + const corePath = path.join(dir, 'core.123'); + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + fs.writeFileSync(corePath, ''); + }); + + after(function () { + mm.restore(); + fs.unlinkSync(corePath); + }); + + it('should ok', async function () { + const job = new ListCoreJob({ coredir: [dir, dir, dir] }); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(1); + expect(params.metrics[0].path).to.be(corePath); + }); + }); + + describe('when coredir specified by /proc/sys/kernel/core_pattern', function () { + const dir = path.join(__dirname, '../logdir'); + const corePath1 = path.join(dir, 'core.12345'); + const corePath2 = path.join(dir, 'coredump_12345'); + const corePath3 = path.join(dir, 'coredump_23456'); + const mock = path.join(dir, 'coredump_%e_%P'); + + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + mm(require('fs'), 'readFileSync', function (path) { + if (path === '/proc/sys/kernel/core_pattern') { + return mock; + } + + return ''; + }); + mm(require('fs'), 'existsSync', function (path) { + if (path === '/proc/sys/kernel/core_pattern') { + return true; + } + + if (path === dir) { + return true; + } + + return false; + }); + fs.writeFileSync(corePath1, ''); + fs.writeFileSync(corePath2, ''); + fs.writeFileSync(corePath3, ''); + }); + + after(function () { + mm.restore(); + fs.unlinkSync(corePath1); + fs.unlinkSync(corePath2); + fs.unlinkSync(corePath3); + }); + + it('should ok', async function () { + const job = new ListCoreJob(); + const params = await job.run(); + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(3); + const paths = params.metrics.map((d) => { + return d.path; + }); + expect(paths.indexOf(corePath1)).not.to.be(-1); + expect(paths.indexOf(corePath2)).not.to.be(-1); + expect(paths.indexOf(corePath3)).not.to.be(-1); + }); + }); + + describe('when core dumped to PWD', function () { + const corePath = path.join(process.env.PWD, 'core.56789'); + before(function () { + mm.syncData(require('os'), 'platform', 'linux'); + mm(require('fs').promises, 'access', async function (path, flag) { + if (path === '') { + return; + } + }); + mm(require('fs').promises, 'readFile', async function (path, flag) { + if (path === '/proc/19672/environ') { + return `a=b\u0000PWD=${process.env.PWD}`; + } + }); + mm(require('../../lib/utils'), 'execAsync', async function () { + return {stdout: '19672 node xxx.js'}; + }); + fs.writeFileSync(corePath, ''); + }); + + it('should ok', async function () { + const job = new ListCoreJob(); + const params = await job.run(); + + expect(params.type).to.be('coredump'); + expect(params.metrics).to.be.ok(); + expect(params.metrics.length).to.be(1); + expect(params.metrics[0].path).to.be(corePath); + }); + + after(function () { + mm.restore(); + fs.unlinkSync(corePath); + }); + }); +}); diff --git a/test/orders/list_core.test.js b/test/orders/list_core.test.js deleted file mode 100644 index 9b9778c..0000000 --- a/test/orders/list_core.test.js +++ /dev/null @@ -1,277 +0,0 @@ -'use strict'; - -const mm = require('mm'); -const fs = require('fs'); -const path = require('path'); -const expect = require('expect.js'); -let listCore = require('../../lib/orders/list_core'); - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - before(function () { - mm(require('child_process'), 'exec', function (cmd, callback) { callback(null, ''); }); - delete require.cache[require.resolve('../../lib/orders/list_core')]; - delete require.cache[require.resolve('child_process')]; - listCore = require('../../lib/orders/list_core'); - console.log(require('child_process').exec.toString()); - }); - - it('no coredirs', function (done) { - listCore.init({ coredir: [] }); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be(null); - done(); - }); - }); - - after(function () { - mm.restore(); - delete require.cache[require.resolve('../../lib/orders/list_core')]; - delete require.cache[require.resolve('child_process')]; - listCore = require('../../lib/orders/list_core'); - }); -}); - - - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - const mock = { - isFile: function () { return true; }, - dev: 2053, - mode: 16893, - nlink: 2, - uid: 1000, - gid: 1000, - rdev: 0, - blksize: 4096, - ino: 2367914, - size: 4096, - blocks: 8, - atimeMs: 1522831557878.927, - mtimeMs: 1522831557778.928 - 70000, - ctimeMs: 1522831557778.928 - 70000, - birthtimeMs: 1522831557778.928, - atime: '2018-04-04T08:45:57.879Z', - mtime: '2018-04-04T08:45:57.779Z', - ctime: '2018-04-04T08:45:57.779Z', - birthtime: '2018-04-04T08:45:57.779Z' - }; - - before(function () { - mm.data(require('fs'), 'stat', mock); - }); - - it('core created before agentx startup will not reported', function (done) { - const dir = path.join(__dirname, '../logdir'); - const corePath = path.join(dir, 'core.123'); - fs.writeFileSync(corePath, ''); - listCore.init({ coredir: [path.join(__dirname, '../logdir')] }); - - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(0); - done(); - fs.unlinkSync(corePath); - }); - }); - - after(function () { - mm.restore(); - }); - -}); - - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - it('should ok coredir not specified', function (done) { - setTimeout(function () { - listCore.init({ coredir: [] }); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(0); - done(); - }); - }, 30); - }); -}); - - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - it('should ok when specify the coredir', function (done) { - const dir = path.join(__dirname, '../logdir'); - const corePath = path.join(dir, 'core.123'); - setTimeout(function () { - listCore.init({ coredir: [path.join(__dirname, '../logdir')] }); - fs.writeFileSync(corePath, ''); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(1); - expect(params.metrics.data[0].path).to.be(corePath); - done(); - fs.unlinkSync(corePath); - }); - }, 30); - }); -}); - - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - it('should ok when coredir not exists', function (done) { - setTimeout(function () { - listCore.init({ coredir: [path.join(__dirname, '../non-logdir')] }); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(0); - done(); - }); - }, 30); - }); - - it('should ok when coredir is empty', function (done) { - setTimeout(function () { - listCore.init({ - coredir: [ - path.join(__dirname, '../logdir/empty') - ] - }); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics.ok).to.be(true); - done(); - }); - }); - }, 30); -}); - - -describe('/lib/orders/list_core.js', function () { - if (require('os').platform() !== 'linux') { - return; - } - - it('should ok when duplicate dir configured', function (done) { - const dir = path.join(__dirname, '../logdir'); - const corePath = path.join(dir, 'core.123'); - setTimeout(function () { - const d = path.join(__dirname, '../logdir'); - listCore.init({ coredir: [d, d, d] }); - fs.writeFileSync(corePath, ''); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(1); - expect(params.metrics.data[0].path).to.be(corePath); - done(); - fs.unlinkSync(corePath); - }); - }, 30); - }); -}); - -describe('should ok when coredir specified by /proc/sys/kernel/core_pattern', function () { - if (require('os').platform() !== 'linux') { - return; - } - - const dir = path.join(__dirname, '../logdir'); - const corePath1 = path.join(dir, 'core.12345'); - const corePath2 = path.join(dir, 'coredump_12345'); - const corePath3 = path.join(dir, 'coredump_23456'); - const mock = path.join(dir, 'coredump_%e_%P'); - before(function () { - mm.syncData(require('fs'), 'readFileSync', mock); - }); - - it('should ok when specify the core dir', function (done) { - - setTimeout(function () { - listCore.init(); - fs.writeFileSync(corePath1, ''); - fs.writeFileSync(corePath2, ''); - fs.writeFileSync(corePath3, ''); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - expect(params.metrics.data.length).to.be(3); - const cores = params.metrics.data; - const paths = [cores[0].path, cores[1].path, cores[2].path]; - expect(paths.indexOf(corePath1)).not.to.be(-1); - expect(paths.indexOf(corePath2)).not.to.be(-1); - expect(paths.indexOf(corePath3)).not.to.be(-1); - done(); - fs.unlinkSync(corePath1); - fs.unlinkSync(corePath2); - fs.unlinkSync(corePath3); - }); - }, 60); - - }); - - after(function () { - mm.restore(); - }); -}); - -describe('should ok when core dumped to PWD', function () { - if (require('os').platform() !== 'linux') { - return; - } - - const corePath = path.join(process.env.PWD, 'core.56789'); - - it('should ok when specify the core dir', function (done) { - listCore.init(); - console.log('cordir:', listCore.coredir); - - fs.writeFileSync(corePath, ''); - setTimeout(function () { - console.log(corePath, fs.existsSync(corePath)); - listCore.run(function (err, params) { - expect(err).not.to.be.ok(); - expect(params.type).to.be('coredump'); - expect(params.metrics).to.be.ok(); - // expect(params.metrics.data.length).to.be(1); - // expect(params.metrics.data[0].path).to.be(corePath); - done(); - fs.unlinkSync(corePath); - }); - - }, 90); - }); - - after(function () { - mm.restore(); - }); -});