<commit_before>const { spawn } = require('child_process')
const path = require('path')
const fs = require('fs')
const os = require('os')
const assert = require('assert')
const mkdirp = require('mkdirp-promise')
const rmfr = require('rmfr')
const colors = require('colors')

const { setWorldConstructor, setDefaultTimeout, Before } = require('cucumber')

class CucumberElectronWorld {
  constructor() {
    this.tempDir = path.resolve(__dirname + '/../../tmp')
  }

  writeFile(filePath, contents) {
    const dir = path.resolve(path.join(this.tempDir, path.dirname(filePath)))
    return mkdirp(dir).then(() => {
      return new Promise((resolve, reject) => {
        fs.writeFile(
          path.join(this.tempDir, filePath),
          contents,
          err => (err ? reject(err) : resolve(err))
        )
      })
    })
  }

  runCommand(command, { env } = { env: {} }) {
    const args = command.split(' ')
    args[0] = args[0].replace(/^cucumber-electron/, 'cucumber-electron.js')
    args[0] = path.resolve(__dirname + '/../../bin/' + args[0])

    return new Promise((resolve, reject) => {
      this.execResult = { stdout: '', stderr: '', output: '', exitCode: null }
      this.printExecResult = () =>
        '------------------------------------\n' +
        `The process exited with code ${this.spawnedProcess.exitCode}\n` +
        '------------------------------------\n' +
        `OUTPUT:\n${this.execResult.output}\n` +
        '------------------------------------\n' +
        `STDOUT:\n${this.execResult.stdout}\n` +
        '------------------------------------\n' +
        `STDERR:\n${this.execResult.stderr}\n` +
        '------------------------------------\n'

      const childEnv = Object.assign(process.env, env)
      this.spawnedProcess = spawn('node', args, {
        cwd: this.tempDir,
        env: childEnv
      })

      this.spawnedProcess.stdout.on('data', chunk => {
        this.execResult.stdout += chunk.toString()
        this.execResult.output += chunk.toString()
      })
      this.spawnedProcess.stderr.on('data', chunk => {
        this.execResult.stderr += chunk.toString()
        this.execResult.output += chunk.toString()
      })
      this.spawnedProcess.on('error', e => {
        reject(e)
      })
      this.spawnedProcess.on('exit', code => (this.execResult.exitCode = code))
      resolve()
    })
  }

  ensureProcessHasExited() {
    if (this.spawnedProcess.exitCode == null) {
      return new Promise(resolve => {
        this.spawnedProcess.on('exit', code => {
          this.execResult.exitCode = code
          resolve()
        })
      })
    }
    return Promise.resolve()
  }

  assertProcessDidNotExit() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        const exitCode = this.spawnedProcess.exitCode
        if (os.platform() === 'win32') {
          spawn('taskkill', ['/pid', this.spawnedProcess.pid, '/T', '/F'])
        } else {
          process.kill(this.spawnedProcess.pid + 1)
        }
        if (exitCode === null) {
          resolve()
        } else {
          reject('The process exited unexpectedly\n' + this.printExecResult())
        }
      }, 1000)
    })
  }

  assertProcessExitedWithCode(expectedExitCode) {
    return this.ensureProcessHasExited().then(() => {
      assert.equal(
        this.spawnedProcess.exitCode,
        expectedExitCode,
        this.printExecResult()
      )
    })
  }

  assertOutputIncludes(expectedOutput, stream = 'output') {
    return this.ensureProcessHasExited().then(() => {
      const normalisedExpectedOutput = expectedOutput.replace('\r\n', '\n')
      const normalisedActualOutput = colors
        .strip(this.execResult[stream])
        .replace('\r\n', '\n')
      if (normalisedActualOutput.indexOf(normalisedExpectedOutput) == -1) {
        throw new Error(
          `Expected ${stream} to include:\n${normalisedExpectedOutput}\n` +
            this.printExecResult()
        )
      }
    })
  }

  assertStdoutIncludes(expectedOutput) {
    return this.assertOutputIncludes(expectedOutput, 'stdout')
  }

  assertStderrIncludes(expectedOutput) {
    // On windows, everything goes out of stderr. Electron.exe needs a shim, or something
    const errorStream = os.platform() === 'win32' ? 'stdout' : 'stderr'
    return this.assertOutputIncludes(expectedOutput, errorStream)
  }

  assertOutputIncludesColours() {
    return this.ensureProcessHasExited().then(() => {
      if (this.execResult.stdout.indexOf('\x1B[39m') === -1) {
        throw new Error('Expected coloured output')
      }
    })
  }
}<commit_msg>Kill all processes in a group. More async/await.<commit_after>const { spawn } = require('child_process')
const path = require('path')
const fs = require('fs')
const os = require('os')
const assert = require('assert')
const mkdirp = require('mkdirp-promise')
const rmfr = require('rmfr')
const colors = require('colors')

const { setWorldConstructor, setDefaultTimeout, Before } = require('cucumber')

class CucumberElectronWorld {
  constructor() {
    this.tempDir = path.resolve(__dirname + '/../../tmp')
  }

  async writeFile(filePath, contents) {
    const dir = path.resolve(path.join(this.tempDir, path.dirname(filePath)))
    return mkdirp(dir).then(() => {
      return new Promise((resolve, reject) => {
        fs.writeFile(
          path.join(this.tempDir, filePath),
          contents,
          err => (err ? reject(err) : resolve(err))
        )
      })
    })
  }

  async runCommand(command, { env } = { env: {} }) {
    const args = command.split(' ')
    args[0] = args[0].replace(/^cucumber-electron/, 'cucumber-electron.js')
    args[0] = path.resolve(__dirname + '/../../bin/' + args[0])

    return new Promise((resolve, reject) => {
      this.execResult = { stdout: '', stderr: '', output: '', exitCode: null }
      this.printExecResult = () =>
        '------------------------------------\n' +
        `The process exited with code ${this.spawnedProcess.exitCode}\n` +
        '------------------------------------\n' +
        `OUTPUT:\n${this.execResult.output}\n` +
        '------------------------------------\n' +
        `STDOUT:\n${this.execResult.stdout}\n` +
        '------------------------------------\n' +
        `STDERR:\n${this.execResult.stderr}\n` +
        '------------------------------------\n'

      const childEnv = Object.assign(process.env, env)
      this.spawnedProcess = spawn('node', args, {
        cwd: this.tempDir,
        env: childEnv,
        detached: true
      })

      this.spawnedProcess.stdout.on('data', chunk => {
        this.execResult.stdout += chunk.toString()
        this.execResult.output += chunk.toString()
      })
      this.spawnedProcess.stderr.on('data', chunk => {
        this.execResult.stderr += chunk.toString()
        this.execResult.output += chunk.toString()
      })
      this.spawnedProcess.on('error', e => {
        reject(e)
      })
      this.spawnedProcess.on('exit', code => (this.execResult.exitCode = code))
      resolve()
    })
  }

  async ensureProcessHasExited() {
    if (this.spawnedProcess.exitCode == null) {
      return new Promise(resolve => {
        this.spawnedProcess.on('exit', code => {
          this.execResult.exitCode = code
          resolve()
        })
      })
    }
    return Promise.resolve()
  }

  async assertProcessDidNotExit() {
    await new Promise(resolve => setTimeout(resolve, 1000))
    const exitCode = this.spawnedProcess.exitCode
    if (exitCode === null) {
      await this.killChild()
    } else {
      throw new Error('The process exited unexpectedly\n' + this.printExecResult())
    }
  }

  async killChild() {
    if (os.platform() === 'win32') {
      spawn('taskkill', ['/pid', this.spawnedProcess.pid, '/T', '/F'])
    } else {
      // Kill the process and all its children (all processes in the same process group).
      // See http://man7.org/linux/man-pages/man2/kill.2.html
      process.kill(-this.spawnedProcess.pid)
    }
  }

  async assertProcessExitedWithCode(expectedExitCode) {
    await this.ensureProcessHasExited()
    assert.equal(
      this.spawnedProcess.exitCode,
      expectedExitCode,
      this.printExecResult()
    )
  }

  async assertOutputIncludes(expectedOutput, stream = 'output') {
    await this.ensureProcessHasExited()
    const normalisedExpectedOutput = expectedOutput.replace('\r\n', '\n')
    const normalisedActualOutput = colors
      .strip(this.execResult[stream])
      .replace('\r\n', '\n')
    if (normalisedActualOutput.indexOf(normalisedExpectedOutput) === -1) {
      throw new Error(
        `Expected ${stream} to include:\n${normalisedExpectedOutput}\n` +
          this.printExecResult()
      )
    }
  }

  async assertStdoutIncludes(expectedOutput) {
    return this.assertOutputIncludes(expectedOutput, 'stdout')
  }

  async assertStderrIncludes(expectedOutput) {
    // On windows, everything goes out of stderr. Electron.exe needs a shim, or something
    const errorStream = os.platform() === 'win32' ? 'stdout' : 'stderr'
    return this.assertOutputIncludes(expectedOutput, errorStream)
  }

  async assertOutputIncludesColours() {
    await this.ensureProcessHasExited()
    if (this.execResult.stdout.indexOf('\x1B[39m') === -1) {
      throw new Error('Expected coloured output')
    }
  }
}
{'fraction_non_alphanumeric': 0.18461703497103626, 'fraction_numerical': 0.004076378459558035, 'mean_word_length': 2.3332141580264567, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3483114', 'n_tokens_mistral': 2803, 'n_tokens_neox': 2740, 'n_words': 517}