const chalk = require('chalk')
const spawn = require('child_process').spawn
const Debug = require('debug')
const fs = require('fs')
const path = require('path')
const terminate = require('terminate')
/**
* @module MutantRunner
* @description Runs a given mutant in a free worker, logging one of the possible results (survived, killed or discarded) and the time of execution.
*
* Execution is done with the `npm test` command inside the worker's directory
*/
module.exports = function MutantRunner ({mutodeInstance, filePath, contentToWrite, log}) {
const debug = Debug(`mutants:${filePath}`)
return async index => {
await new Promise(resolve => {
const startTime = process.hrtime()
fs.writeFileSync(`.mutode/mutode-${mutodeInstance.id}-${index}/${filePath}`, contentToWrite)
const child = spawn(mutodeInstance.npmCommand, ['test'], {cwd: path.resolve(`.mutode/mutode-${mutodeInstance.id}-${index}`)})
child.stderr.on('data', data => {
debug(data.toString())
})
let timedout = false
const timeout = setTimeout(() => {
terminate(child.pid)
timedout = true
}, mutodeInstance.timeout).unref()
child.on('exit', (code, signal) => {
const endTime = process.hrtime(startTime)
const endTimeMS = (endTime[0] * 1e3 + endTime[1] / 1e6).toFixed(0)
const timeDiff = chalk.gray(`${endTimeMS} ms`)
clearTimeout(timeout)
if (code === 0) {
console.log(`${log}\t${chalk.bgRed('survived')} ${timeDiff}`)
mutodeInstance.survived++
} else if (signal || timedout) {
console.log(`${log}\t${chalk.bgBlue('discarded (timeout)')} ${timeDiff}`)
mutodeInstance.discarded++
} else {
console.log(`${log}\t${chalk.bgGreen('killed')} ${timeDiff}`)
mutodeInstance.killed++
}
// console.log('exit', code)
resolve()
})
})
}
}