<commit_before>'use strict'

const MiniPass = require('minipass')

const extraFromError = require('./extra-from-error.js')
const assert = require('assert')
const cleanYamlObject = require('./clean-yaml-object.js')

const domain = require('domain')
const util = require('util')

const Parser = require('tap-parser')

const ownOr = require('own-or')
const ownOrEnv = require('own-or-env')

class Base extends MiniPass {
  constructor (options) {
    options = options || {}
    super(options)
    this.start = 0
    this.hrtime = null
    this.time = null
    this.readyToProcess = false
    this.options = options
    this.grep = ownOr(options, 'grep', [])
    this.grepInvert = ownOr(options, 'grepInvert', false)
    this.parent = ownOr(options, 'parent', null)
    this.bail = ownOrEnv(options, 'bail', 'TAP_BAIL', true)
    this.name = ownOr(options, 'name', '')
    if (!this.name)
      this.name = ''
    else
      this.name = this.name.replace(/[\n\r\s\t]/g, ' ')
    this.indent = ownOr(options, 'indent', '')
    this.silent = !!options.silent
    this.buffered = !!options.buffered || !!options.silent
    this.finished = false
    this.strict = ownOrEnv(options, 'strict', 'TAP_STRICT', true)
    this.omitVersion = !!options.omitVersion
    this.preserveWhitespace = ownOr(options, 'preserveWhitespace', true)
    this.jobs = +ownOrEnv(options, 'jobs', 'TAP_JOBS') || 0
    this.skip = ownOr(options, 'skip', false)
    this.todo = ownOr(options, 'todo', false)
    this.runOnly = ownOr(options, 'runOnly', false)
    this.setupParser(options)
    this.finished = false
    this.output = ''
    this.results = null
    this.bailedOut = false
    if (this.skip || this.todo)
      this.main = Base.prototype.main

    domain.create().add(this)
    this.domain.on('error', this.threw.bind(this))

    const doDebug = typeof options.debug === 'boolean' ? options.debug
      : /\btap\b/i.test(process.env.NODE_DEBUG || '')

    if (doDebug)
      this.debug = debug
  }

  passing () {
    return this.parser.ok
  }

  setTimeout (n) {
    if (!this.hrtime)
      this.hrtime = process.hrtime()

    if (!n) {
      clearTimeout(this.timer)
      this.timer = null
    } else {
      this.start = Date.now()
      this.timer = setTimeout(this.timeout.bind(this), n)
      if (this.timer.unref)
        this.timer.unref()
    }
  }

  threw (er, extra, proxy) {
    if (this.name && !proxy)
      er.test = this.name

    const message = er.message

    if (!extra)
      extra = extraFromError(er, extra, this.options)

    if (this.results || this.ended) {
      this.results.ok = false
      if (this.parent)
        this.parent.threw(er, extra, true)
      else if (!er.stack)
        console.error(er)
      else {
        er.message = message
        delete extra.stack
        delete extra.at
        console.error('%s: %s', er.name || 'Error', message)
        console.error(er.stack.split(/\n/).slice(1).join('\n'))
        console.error(extra)
      }
    } else
      this.parser.ok = false

    return extra
  }

  timeout (options) {
    this.setTimeout(false)
    const er = new Error('timeout!')
    options = options || {}
    options.expired = options.expired || this.name
    this.threw(new Error('timeout!'), options)
  }

  main (cb) {
    cb()
  }

  online (line) {
    this.debug('LINE %j', line)
    return this.write(this.indent + line)
  }

  write (c, e) {
    assert.equal(typeof c, 'string')
    assert.equal(c.substr(-1), '\n')

    if (this.buffered) {
      this.output += c
      return true
    }

    return super.write(c, e)
  }

  onbail (reason) {
    this.bailedOut = reason || true
    this.emit('bailout', reason)
  }

  oncomplete (results) {
    if (this.hrtime) {
      this.hrtime = process.hrtime(this.hrtime)
      this.time = Math.round(this.hrtime[0] * 1e6 + this.hrtime[1] / 1e3) / 1e3
    }

    this.debug('ONCOMPLETE %j %j', this.name, results)

    if (this.results)
      Object.keys(this.results)
        .forEach(k => results[k] = this.results[k])

    this.results = results
    this.emit('complete', results)
    const failures = results.failures
      .filter(f => f.tapError)
      .map(f => {
        delete f.diag
        delete f.ok
        return f
      })

    if (failures.length)
      this.options.failures = failures

    this.onbeforeend()
    this.emit('end')
    this.ondone()
  }

  onbeforeend () {}
  ondone () {}

  setupParser (options) {
    this.parser = new Parser({
      bail: this.bail,
      strict: this.strict,
      omitVersion: this.omitVersion,
      preserveWhitespace: this.preserveWhitespace
    })
    assert(this.parser.preserveWhitespace)
    this.parser.on('line', this.online.bind(this))
    this.parser.once('bailout', this.onbail.bind(this))
    this.parser.on('complete', this.oncomplete.bind(this))
  }

  _read (n) {
    // this.emit('readable')
    // this.debug('_read %j', this.name, arguments)
  }

  inspect () {
    return this.constructor.name + ' ' + util.inspect({
      name: this.name,
      jobs: this.jobs,
      buffered: this.buffered,
      occupied: this.occupied,
      pool: this.pool,
      queue: this.queue,
      subtests: this.subtests,
      output: this.output,
      skip: this.skip,
      todo: this.todo,
      only: this.only,
      results: this.results,
      options: [
        'autoend',
        'command',
        'args',
        'stdio',
        'env',
        'cwd',
        'exitCode',
        'signal',
        'expired',<commit_msg>No need for a dummy _read in MiniPass classes<commit_after>'use strict'

const MiniPass = require('minipass')

const extraFromError = require('./extra-from-error.js')
const assert = require('assert')
const cleanYamlObject = require('./clean-yaml-object.js')

const domain = require('domain')
const util = require('util')

const Parser = require('tap-parser')

const ownOr = require('own-or')
const ownOrEnv = require('own-or-env')

class Base extends MiniPass {
  constructor (options) {
    options = options || {}
    super(options)
    this.start = 0
    this.hrtime = null
    this.time = null
    this.readyToProcess = false
    this.options = options
    this.grep = ownOr(options, 'grep', [])
    this.grepInvert = ownOr(options, 'grepInvert', false)
    this.parent = ownOr(options, 'parent', null)
    this.bail = ownOrEnv(options, 'bail', 'TAP_BAIL', true)
    this.name = ownOr(options, 'name', '')
    if (!this.name)
      this.name = ''
    else
      this.name = this.name.replace(/[\n\r\s\t]/g, ' ')
    this.indent = ownOr(options, 'indent', '')
    this.silent = !!options.silent
    this.buffered = !!options.buffered || !!options.silent
    this.finished = false
    this.strict = ownOrEnv(options, 'strict', 'TAP_STRICT', true)
    this.omitVersion = !!options.omitVersion
    this.preserveWhitespace = ownOr(options, 'preserveWhitespace', true)
    this.jobs = +ownOrEnv(options, 'jobs', 'TAP_JOBS') || 0
    this.skip = ownOr(options, 'skip', false)
    this.todo = ownOr(options, 'todo', false)
    this.runOnly = ownOr(options, 'runOnly', false)
    this.setupParser(options)
    this.finished = false
    this.output = ''
    this.results = null
    this.bailedOut = false
    if (this.skip || this.todo)
      this.main = Base.prototype.main

    domain.create().add(this)
    this.domain.on('error', this.threw.bind(this))

    const doDebug = typeof options.debug === 'boolean' ? options.debug
      : /\btap\b/i.test(process.env.NODE_DEBUG || '')

    if (doDebug)
      this.debug = debug
  }

  passing () {
    return this.parser.ok
  }

  setTimeout (n) {
    if (!this.hrtime)
      this.hrtime = process.hrtime()

    if (!n) {
      clearTimeout(this.timer)
      this.timer = null
    } else {
      this.start = Date.now()
      this.timer = setTimeout(this.timeout.bind(this), n)
      if (this.timer.unref)
        this.timer.unref()
    }
  }

  threw (er, extra, proxy) {
    if (this.name && !proxy)
      er.test = this.name

    const message = er.message

    if (!extra)
      extra = extraFromError(er, extra, this.options)

    if (this.results || this.ended) {
      this.results.ok = false
      if (this.parent)
        this.parent.threw(er, extra, true)
      else if (!er.stack)
        console.error(er)
      else {
        er.message = message
        delete extra.stack
        delete extra.at
        console.error('%s: %s', er.name || 'Error', message)
        console.error(er.stack.split(/\n/).slice(1).join('\n'))
        console.error(extra)
      }
    } else
      this.parser.ok = false

    return extra
  }

  timeout (options) {
    this.setTimeout(false)
    const er = new Error('timeout!')
    options = options || {}
    options.expired = options.expired || this.name
    this.threw(new Error('timeout!'), options)
  }

  main (cb) {
    cb()
  }

  online (line) {
    this.debug('LINE %j', line)
    return this.write(this.indent + line)
  }

  write (c, e) {
    assert.equal(typeof c, 'string')
    assert.equal(c.substr(-1), '\n')

    if (this.buffered) {
      this.output += c
      return true
    }

    return super.write(c, e)
  }

  onbail (reason) {
    this.bailedOut = reason || true
    this.emit('bailout', reason)
  }

  oncomplete (results) {
    if (this.hrtime) {
      this.hrtime = process.hrtime(this.hrtime)
      this.time = Math.round(this.hrtime[0] * 1e6 + this.hrtime[1] / 1e3) / 1e3
    }

    this.debug('ONCOMPLETE %j %j', this.name, results)

    if (this.results)
      Object.keys(this.results)
        .forEach(k => results[k] = this.results[k])

    this.results = results
    this.emit('complete', results)
    const failures = results.failures
      .filter(f => f.tapError)
      .map(f => {
        delete f.diag
        delete f.ok
        return f
      })

    if (failures.length)
      this.options.failures = failures

    this.onbeforeend()
    this.emit('end')
    this.ondone()
  }

  onbeforeend () {}
  ondone () {}

  setupParser (options) {
    this.parser = new Parser({
      bail: this.bail,
      strict: this.strict,
      omitVersion: this.omitVersion,
      preserveWhitespace: this.preserveWhitespace
    })
    assert(this.parser.preserveWhitespace)
    this.parser.on('line', this.online.bind(this))
    this.parser.once('bailout', this.onbail.bind(this))
    this.parser.on('complete', this.oncomplete.bind(this))
  }

  inspect () {
    return this.constructor.name + ' ' + util.inspect({
      name: this.name,
      jobs: this.jobs,
      buffered: this.buffered,
      occupied: this.occupied,
      pool: this.pool,
      queue: this.queue,
      subtests: this.subtests,
      output: this.output,
      skip: this.skip,
      todo: this.todo,
      only: this.only,
      results: this.results,
      options: [
        'autoend',
        'command',
        'args',
        'stdio',
        'env',
        'cwd',
        'exitCode',
        'signal',
        'expired',
{'fraction_non_alphanumeric': 0.15079801871216292, 'fraction_numerical': 0.002201430930104568, 'mean_word_length': 2.4459544879898862, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '4838219', 'n_tokens_mistral': 3755, 'n_tokens_neox': 3686, 'n_words': 750}