var test = require('tap').test;
var path = require('path');
var concat = require('concat-stream');
var spawn = require('child_process').spawn;

var stripFullStack = require('./common').stripFullStack;

test(function (t) {
    t.plan(2);
    var ps = spawn(process.execPath, [path.join(__dirname, 'double_end', 'double.js')]);
    ps.on('exit', function (code) {
        t.equal(code, 1);
    });
    ps.stdout.pipe(concat(function (body) {
        // The implementation of node's timer library has changed over time. We
        // need to reverse engineer the error we expect to see.

        // This code is unfortunately by necessity highly coupled to node
        // versions, and may require tweaking with future versions of the timers
        // library.
        function doEnd() { throw new Error(); };
        var to = setTimeout(doEnd, 5000);
        clearTimeout(to);
        to._onTimeout = doEnd;

        var stackExpected;
        var atExpected;
        try {
            to._onTimeout();
        }
        catch (e) {
            stackExpected = stripFullStack(e.stack).split('\n')[1];
            stackExpected = stackExpected.replace('double_end.js', 'double_end/double.js');
            stackExpected = stackExpected.trim();
            atExpected = stackExpected.replace(/^at\s+/, 'at: ');
        }

        var stripped = stripFullStack(body.toString('utf8'));
        t.equal(stripped, [
            'TAP version 13',
            '# double end',
            'ok 1 should be equal',
            'not ok 2 .end() called twice',
            '  ---',
            '    operator: fail',
            '    ' + atExpected,
            '    stack: |-',
            '      Error: .end() called twice',
            '          [... stack stripped ...]',
            '          ' + stackExpected,
            '          [... stack stripped ...]',
            '  ...',
            '',
            '1..2',
            '# tests 2',
            '# pass  1',
            '# fail  1',
        ].join('\n') + '\n\n');
    }));
});
