/*
 * Copyright 2020 Trent Mick
 *
 * If available, test dtrace support.
 */

var spawn = require('child_process').spawn;
var format = require('util').format;
var test = require('tap').test;

var bunyan = require('../../lib/bunyan');


// Determine if we can run the dtrace tests.
var dtracePlats = ['sunos', 'darwin', 'freebsd'];
var runDtraceTests = true;
try {
    require('dtrace-provider');
} catch (e) {
    console.log('# skip dtrace tests: no dtrace-provider module');
    runDtraceTests = false;
}
if (!runDtraceTests) {
    /* pass through */
} else if (dtracePlats.indexOf(process.platform) === -1) {
    console.log('# skip dtrace tests: not on a platform with dtrace');
    runDtraceTests = false;
} else if (process.env.SKIP_DTRACE) {
    console.log('# skip dtrace tests: SKIP_DTRACE envvar set');
    runDtraceTests = false;
} else if (process.getgid() !== 0) {
    console.log('# skip dtrace tests: gid is not 0, run with `sudo`');
    runDtraceTests = false;
}
if (runDtraceTests) {


test('basic dtrace', function (t) {
    var argv = ['dtrace', '-Z', '-x', 'strsize=4k', '-qn',
        'bunyan$target:::log-*{printf("%s", copyinstr(arg0))}',
        '-c', format('node %s/log-some.js', __dirname)];
    var dtrace = spawn(argv[0], argv.slice(1));
    //console.error('ARGV: %j', argv);
    //console.error('CMD: %s', argv.join(' '));

    var traces = [];
    dtrace.stdout.on('data', function (data) {
        //console.error('DTRACE STDOUT:', data.toString());
        traces.push(data.toString());
    });
    dtrace.stderr.on('data', function (data) {
        console.error('DTRACE STDERR:', data.toString());
    });
    dtrace.on('exit', function (code) {
        t.notOk(code, 'dtrace exited cleanly');
        traces = traces.join('').split('\n')
            .filter(function (t) { return t.trim().length })
            .map(function (t) { return JSON.parse(t) });
        t.equal(traces.length, 2, 'got 2 log records');
        if (traces.length) {
            t.equal(traces[0].level, bunyan.DEBUG);
            t.equal(traces[0].foo, 'bar');
            t.equal(traces[1].level, bunyan.TRACE);
            t.equal(traces[1].msg, 'hi at trace');
        }
        t.end();
    });
});


/*
 * Run a logger that logs a couple records every second.
 * Then run `bunyan -p PID` to capture.
 * Let those run for a few seconds to ensure dtrace has time to attach and
 * capture something.
 */
test('bunyan -p', function (t) {
    var p = spawn('node', [__dirname + '/log-some-loop.js']);

    var bunyanP = spawn('node',
        [__dirname + '/../bin/bunyan', '-p', String(p.pid), '-0']);
    var traces = [];
    bunyanP.stdout.on('data', function (data) {
        //console.error('BUNYAN -P STDOUT:', data.toString());
        traces.push(data.toString());
    });
    bunyanP.stderr.on('data', function (data) {
        console.error('BUNYAN -P STDERR:', data.toString());
    });
    bunyanP.on('exit', function (code) {
        traces = traces.join('').split('\n')
            .filter(function (t) { return t.trim().length })
            .map(function (t) { return JSON.parse(t) });
        t.ok(traces.length >= 3, 'got >=3 log records: ' + traces.length);
        if (traces.length >= 3) {
            if (traces[0].level !== bunyan.DEBUG) {
                traces.shift();
            }
            t.equal(traces[0].level, bunyan.DEBUG);
            t.equal(traces[0].foo, 'bar');
            t.equal(traces[1].level, bunyan.TRACE);
            t.equal(traces[1].msg, 'hi at trace');
        }
        t.end();
    });

    // Give it a few seconds to ensure we get some traces.
    setTimeout(function () {
        p.kill();
        bunyanP.kill();
    }, 5000);
});


} /* end of `if (runDtraceTests)` */
