CasperSecurity

Current Path : /usr/share/nodejs/tap/lib/
Upload File :
Current File : //usr/share/nodejs/tap/lib/test.js

'use strict'
// We need TWO queues (work and subtest) and one jobs pool
//
// The pool stores buffered subtests being run in parallel.
//
// When new subtests are created, they get put in the work queue and also
// in the subtests queue if they are buffered and jobs>0.  When we put a
// test in the subtest queue, we also process it.
//
// Processing the subtest queue means moving tests into the jobs pool until
// the jobs pool length is at this.jobs
//
// Any output functions get put in the work queue if its length > 0 (ie,
// no cutting the line)
//
// Processing the work queue means walking until we run out of things, or
// encounter an unfinished test.  When we encounter ANY kind of test, we
// block until its output is completed, dumping it all into the parser.

const Base = require('./base.js')
const Spawn = require('./spawn.js')
const Stdin = require('./stdin.js')
const Deferred = require('trivial-deferred')
const Pool = require('yapool')
const TestPoint = require('./point.js')
const parseTestArgs = require('./parse-test-args.js')
const loop = require('function-loop')
const path = require('path')

const extraFromError = require('./extra-from-error.js')
const tsame = require('tsame') // same thing, strict or not
const tmatch = require('tmatch') // ok with partial estimates
const stack = require('./stack.js')
const synonyms = require('./synonyms.js')
const assert = require('assert')
const util = require('util')
const ownOr = require('own-or')
const ownOrEnv = require('own-or-env')
const bindObj = require('bind-obj-methods')
const cwd = process.cwd()

// A sigil object for implicit end() calls that should not
// trigger an error if the user then calls t.end()
const IMPLICIT = Symbol('implicit t.end()')

// Sigil to put in the queue to signal the end of all things
const EOF = Symbol('EOF')

const _currentAssert = Symbol('_currentAssert')
const _end = Symbol('_end')
const _snapshot = Symbol('_snapshot')
const Snapshot = require('./snapshot.js')

const hasOwn = (obj, key) =>
  Object.prototype.hasOwnProperty.call(obj, key)

const isRegExp = re =>
  Object.prototype.toString.call(re) === '[object RegExp]'

class Test extends Base {
  constructor (options) {
    options = options || {}
    super(options)
    this.pushedEnd = false
    this.jobs = ownOr(options, 'jobs', 1)

    this.subtests = []
    this.pool = new Pool()
    this.queue = ['TAP version 13\n']

    // snapshots are keyed off of the main file that loads the
    // root test object. Typically, this is the TAP object.
    // To do this, we climb the ladder and only save in the teardown
    // of that root (parentless) test object.  This allows handling
    // cases where the same test name can be used multiple times
    // in a single test file, which would otherwise clobber snapshots.
    this.writeSnapshot = ownOrEnv(
      options, 'snapshot', 'TAP_SNAPSHOT', true)
    if (this.parent && this.parent[_snapshot])
      this[_snapshot] = this.parent[_snapshot]
    else
      this[_snapshot] = new Snapshot(this)

    this.noparallel = false
    if (options.cb)
      this.cb = this.domain.bind(options.cb)

    this.occupied = false
    this[_currentAssert] = null
    this.count = 0
    this.n = 0
    this.ended = false
    this.explicitEnded = false
    this.multiEndThrew = false
    this.assertAt = null
    this.assertStack = null
    this.planEnd = -1
    this.onBeforeEach = []
    this.onAfterEach = []
    this.ranAfterEach = false

    // bind all methods to this object, so we can pass t.end as a callback
    // and do `const test = require('tap').test` like people do.
    const bound = Object.create(null)
    bindObj(this, this, bound)
    bindObj(this, Object.getPrototypeOf(this), bound)
    bindObj(this, Test.prototype, bound)
  }

  spawn (cmd, args, options, name) {
    if (typeof args === 'string')
      args = [ args ]

    args = args || []

    if (typeof options === 'string') {
      name = options
      options = {}
    }

    options = options || {}
    options.name = ownOr(options, 'name', name)
    options.command = cmd
    options.args = args

    return this.sub(Spawn, options, Test.prototype.spawn)
  }

  sub (Class, extra, caller) {
    if (this.results || this.ended) {
      const er = new Error('cannot create subtest after parent test end')
      this.threw(er)
      return Promise.resolve(this)
    }

    if (!extra.skip && this.grep.length) {
      const m = this.grep[0].test(extra.name)
      const match = this.grepInvert ? !m : m
      if (!match) {
        const p = 'filter' + (this.grepInvert ? ' out' : '') + ': '
        extra.skip = p + this.grep[0]
      }
    }

    if (extra.only && !this.runOnly)
      this.comment('%j has `only` set but all tests run', extra.name)

    if (this.runOnly && !extra.only)
      extra.skip = 'filter: only'

    if (extra.todo || extra.skip) {
      this.pass(extra.name, extra)
      return Promise.resolve(this)
    }

    if (!extra.grep) {
      extra.grep = this.grep.slice(1)
      extra.grepInvert = this.grepInvert
    }

    extra.indent = '    '
    if (this.jobs > 1 && process.env.TAP_BUFFER === undefined)
      extra.buffered = ownOr(extra, 'buffered', true)
    else
      extra.buffered = ownOrEnv(extra, 'buffered', 'TAP_BUFFER', true)

    extra.bail = ownOr(extra, 'bail', this.bail)
    extra.parent = this
    extra.stack = stack.captureString(80, caller)
    const t = new Class(extra)

    this.queue.push(t)
    this.subtests.push(t)

    const d = new Deferred()
    t.deferred = d
    this.process()
    return d.promise
  }

  todo (name, extra, cb) {
    extra = parseTestArgs(name, extra, cb)
    extra.todo = true
    return this.sub(Test, extra, Test.prototype.todo)
  }

  skip (name, extra, cb) {
    extra = parseTestArgs(name, extra, cb)
    extra.skip = true
    return this.sub(Test, extra, Test.prototype.skip)
  }

  only (name, extra, cb) {
    extra = parseTestArgs(name, extra, cb)
    extra.only = true
    return this.sub(Test, extra, Test.prototype.only)
  }

  test (name, extra, cb) {
    extra = parseTestArgs(name, extra, cb)
    return this.sub(Test, extra, Test.prototype.test)
  }

  stdin (name, extra) {
    /* istanbul ignore next */
    extra = parseTestArgs(name, extra, false, '/dev/stdin')
    return this.sub(Stdin, extra, Test.prototype.stdin)
  }

  bailout (message) {
    if (this.parent && (this.results || this.ended))
      this.parent.bailout(message)
    else {
      this.process()
      message = message ? ' ' + ('' + message).trim() : ''
      message = message.replace(/[\r\n]/g, ' ')
      this.parser.write('Bail out!' + message + '\n')
    }
    this.end(IMPLICIT)
    this.process()
  }

  comment () {
    const body = util.format.apply(util, arguments)
    const message = '# ' + body.split(/\r?\n/).join('\n# ') + '\n'

    if (this.results)
      this.write(message)
    else
      this.queue.push(message)
    this.process()
  }

  timeout (options) {
    options = options || {}
    options.expired = options.expired || this.name
    if (this.occupied)
      this.occupied.timeout(options)
    else
      Base.prototype.timeout.call(this, options)
    this.end(IMPLICIT)
  }

  main (cb) {
    this.setTimeout(this.options.timeout)
    this.debug('MAIN pre', this)

    const end = () => {
      this.debug(' > implicit end for promise')
      this.end(IMPLICIT)
      done()
    }

    const done = (er) => {
      if (er)
        this.threw(er)

      if (this.results || this.bailedOut)
        cb()
      else
        this.ondone = cb
    }

    // This bit of overly clever line-noise wraps the call to user-code
    // in a try-catch. We can't rely on the domain for this yet, because
    // the 'end' event can trigger a throw after the domain is unhooked,
    // but before this is no longer the official "active test"
    const ret = (() => {
      try {
        return this.cb(this)
      } catch (er) {
        this.threw(er)
      }
    })()

    if (ret && ret.then) {
      this.promise = ret
      ret.tapAbortPromise = done
      ret.then(end, done)
    } else
      done()

    this.debug('MAIN post', this)
  }

  process () {
    if (this.processing)
      return this.debug(' < already processing')

    this.debug('\nPROCESSING(%s)', this.name, this.queue.length)
    this.processing = true

    while (!this.occupied) {
      const p = this.queue.shift()
      if (!p)
        break
      if (p instanceof Base) {
        this.processSubtest(p)
      } else if (p === EOF) {
        this.debug(' > EOF', this.name)
        // I AM BECOME EOF, DESTROYER OF STREAMS
        if (this.writeSnapshot)
          this[_snapshot].save()
        this.parser.end()
      } else if (p instanceof TestPoint) {
        this.debug(' > TESTPOINT')
        this.parser.write(p.ok + (++this.n) + p.message)
      } else if (typeof p === 'string') {
        this.debug(' > STRING')
        this.parser.write(p)
      } else {
        /* istanbul ignore else */
        if (Array.isArray(p)) {
          this.debug(' > METHOD')
          const m = p.shift()
          this[m].apply(this, p)
        } else {
          throw new Error('weird thing got in the queue')
        }
      }
    }

    while (!this.noparallel && this.pool.length < this.jobs) {
      const p = this.subtests.shift()
      if (!p)
        break

      if (!p.buffered) {
        this.noparallel = true
        break
      }

      this.debug('start subtest', p)
      this.pool.add(p)
      if (this.bailedOut)
        this.onbufferedend(p)
      else
        this.runBeforeEach(p, () =>
          p.main(() => this.onbufferedend(p)))
    }

    this.debug('done processing', this.queue, this.occupied)
    this.processing = false

    // just in case any tests ended, and we have sync stuff still
    // waiting around in the queue to be processed
    if (!this.occupied && this.queue.length)
      this.process()

    this.maybeAutoend()
  }

  processSubtest (p) {
    this.debug(' > subtest')
    this.occupied = p
    if (!p.buffered) {
      if (this.bailedOut)
        return this.onindentedend(p)
      this.debug(' > subtest indented')
      p.pipe(this.parser, { end: false })
      this.runBeforeEach(p, () =>
        this.writeSubComment(p, () =>
          p.main(() => this.onindentedend(p))))
    } else if (p.readyToProcess) {
      this.debug(' > subtest buffered, finished')
      // finished!  do the thing!
      this.occupied = null
      if (!p.passing() || !p.silent) {
        this.queue.unshift(['emitSubTeardown', p])
        this.printResult(p.passing(), p.name, p.options, true)
      }
    } else {
      this.occupied = p
      this.debug(' > subtest buffered, unfinished', p)
      // unfinished buffered test.
      // nothing to do yet, just leave it there.
      this.queue.unshift(p)
    }
  }

  emitSubTeardown (p) {
    try {
      p.emit('teardown')
    } catch (er) {
      delete p.options.time
      p.threw(er)
    }
  }

  writeSubComment (p, cb) {
    const comment = '# Subtest' +
      (p.name ? ': ' + p.name : '') +
      '\n'
    this.parser.write(comment)
    cb()
  }

  onbufferedend (p) {
    delete p.ondone
    p.results = p.results || {}
    p.readyToProcess = true
    const to = p.options.timeout
    const dur = (to && p.passing()) ? Date.now() - p.start : null
    if (dur && dur > to)
      p.timeout()
    else
      p.setTimeout(false)
    this.debug('%s.onbufferedend', this.name, p.name, p.results.bailout)
    this.pool.remove(p)
    p.options.tapChildBuffer = p.output || ''
    p.options.stack = ''
    if (p.time)
      p.options.time = p.time
    if (this.occupied === p)
      this.occupied = null
    p.deferred.resolve(this)
    this.process()
  }

  onindentedend (p) {
    delete p.ondone
    this.debug('onindentedend', p)
    this.noparallel = false
    const sti = this.subtests.indexOf(p)
    if (sti !== -1)
      this.subtests.splice(sti, 1)
    p.readyToProcess = true
    p.results = p.results || {}
    if (p.time)
      p.options.time = p.time
    const to = p.options.timeout
    const dur = (to && p.passing()) ? Date.now() - p.start : null
    if (dur && dur > to)
      p.timeout()
    else
      p.setTimeout(false)
    this.debug('onindentedend %s(%s)', this.name, p.name)
    if (!p.bailedOut)
      assert.equal(this.occupied, p)
    this.occupied = null
    this.debug('OIE(%s) b>shift into queue', this.name, this.queue)
    p.options.stack = ''

    this.queue.unshift(['emitSubTeardown', p])
    this.printResult(p.passing(), p.name, p.options, true)

    this.debug('OIE(%s) shifted into queue', this.name, this.queue)
    p.deferred.resolve(this)
    this.process()
  }

  addAssert (name, length, fn) {
    if (!name)
      throw new TypeError('name is required for addAssert')

    if (!(typeof length === 'number' && length >= 0))
      throw new TypeError('number of args required')

    if (typeof fn !== 'function')
      throw new TypeError('function required for addAssert')

    if (Test.prototype[name] || this[name])
      throw new TypeError('attempt to re-define `' + name + '` assert')

    function ASSERT () {
      this.currentAssert = ASSERT
      const args = new Array(length + 2)
      for (let i = 0; i < length; i++) {
        args[i] = arguments[i]
      }
      if (typeof arguments[length] === 'object') {
        args[length] = ''
        args[length + 1] = arguments[length]
      } else {
        args[length] = arguments[length] || ''
        args[length + 1] = arguments[length + 1] || {}
      }

      return fn.apply(this, args)
    }
    this[name] = ASSERT
  }

  printResult (ok, message, extra, front) {
    const n = this.count + 1
    this.currentAssert = Test.prototype.printResult
    const fn = this[_currentAssert]
    this[_currentAssert] = null

    if (this.planEnd !== -1 && n > this.planEnd) {
      if (!this.passing())
        return

      const failMessage = this.explicitEnded
          ? 'test after end() was called'
          : 'test count exceeds plan'

      const er = new Error(failMessage)
      Error.captureStackTrace(er, fn)
      er.test = this.name
      er.plan = this.planEnd
      this.threw(er)
      return
    }

    extra = extra || {}

    if (extra.expectFail)
      ok = !ok

    if (this.assertAt) {
      extra.at = this.assertAt
      this.assertAt = null
    }

    if (this.assertStack) {
      extra.stack = this.assertStack
      this.assertStack = null
    }

    if (hasOwn(extra, 'stack') && !hasOwn(extra, 'at'))
      extra.at = stack.parseLine(extra.stack.split('\n')[0])

    if (!ok && !extra.skip && !hasOwn(extra, 'at')) {
      assert.equal(typeof fn, 'function')
      extra.at = stack.at(fn)
      if (!extra.todo)
        extra.stack = stack.captureString(80, fn)
    }

    const diagnostic =
      typeof extra.diagnostic === 'boolean' ? extra.diagnostic
      : process.env.TAP_DIAG === '0' ? false
      : process.env.TAP_DIAG === '1' ? true
      : extra.skip ? false
      : !ok

    if (diagnostic)
      extra.diagnostic = true

    this.count = n
    message = message + ''
    const res = { ok: ok, message: message, extra: extra }
    const output = new TestPoint(ok, message, extra)
    // when we jump the queue, skip an extra line
    if (front)
      output.message = output.message.trimRight() + '\n\n'

    if (front) {
      this.emit('result', res)
      this.parser.write(output.ok + (++this.n) + output.message)
    } else
      this.queue.push(['emit', 'result', res], output)

    if (this.planEnd === this.count)
      this.end(IMPLICIT)

    this.process()
  }

  pragma (set) {
    const p = Object.keys(set).reduce((acc, i) =>
      acc + 'pragma ' + (set[i] ? '+' : '-') + i + '\n', '')
    this.queue.push(p)
    this.process()
  }

  plan (n, comment) {
    if (this.bailedOut)
      return

    if (this.planEnd !== -1) {
      throw new Error('Cannot set plan more than once')
    }

    if (typeof n !== 'number' || n < 0) {
      throw new TypeError('plan must be a number')
    }

    // Cannot get any tests after a trailing plan, or a plan of 0
    const ending = this.count !== 0 || n === 0

    if (n === 0 && comment && !this.options.skip)
      this.options.skip = comment

    this.planEnd = n
    comment = comment ? ' # ' + comment.trim() : ''
    this.queue.push('1..' + n + comment + '\n')

    if (ending)
      this.end(IMPLICIT)
    else
      this.process()
  }

  end (implicit) {
    this.debug('END implicit=%j', implicit === IMPLICIT)
    if (this.ended && implicit === IMPLICIT)
      return

    // beyond here we have to be actually done with things, or else
    // the semantic checks on counts and such will be off.
    if (!queueEmpty(this) || this.occupied) {
      if (!this.pushedEnd)
        this.queue.push(['end', implicit])
      this.pushedEnd = true
      return this.process()
    }

    if (!this.ranAfterEach && this.parent) {
      this.ranAfterEach = true
      this.parent.runAfterEach(this, () => this[_end](implicit))
      return
    } else
      this[_end](implicit)
  }

  [_end] (implicit) {
    this.ended = true

    if (implicit !== IMPLICIT && !this.multiEndThrew) {
      if (this.explicitEnded) {
        this.multiEndThrew = true
        const er = new Error('test end() method called more than once')
        Error.captureStackTrace(er, this[_currentAssert] ||
          Test.prototype[_end])
        er.test = this.name
        this.threw(er)
        return
      }
      this.explicitEnded = true
    }

    if (this.planEnd === -1) {
      this.debug('END(%s) implicit plan', this.name, this.count)
      this.plan(this.count)
    }

    this.queue.push(EOF)
    this.process()
  }

  threw (er, extra, proxy) {
    this.debug('THREW', er.message, extra, proxy)

    // event emitters 'error' events need to re-throw so that they
    // can jump out of the flow like a normal throw.  They'll just
    // end up back here once that happens, though, unless there's a
    // try/catch somewhere in the call stack.
    if (er.domainEmitter) {
      delete er.domainEmitter
      throw er
    }

    if (this.name && !proxy)
      er.test = this.name
    if (!proxy)
      extra = extraFromError(er, extra, this.options)
    Base.prototype.threw.call(this, er, extra, proxy)

    if (!this.results) {
      this.fail(extra.message || er.message, extra)
      if (!proxy)
        this.end(IMPLICIT)
    }
    this.process()
  }

  runBeforeEach (who, cb) {
    if (this.parent)
      this.parent.runBeforeEach(who, () => {
        loop(who, this.onBeforeEach, cb, who.threw)
      })
    else
      loop(who, this.onBeforeEach, cb, who.threw)
  }

  runAfterEach (who, cb) {
    loop(who, this.onAfterEach, () => {
      if (this.parent)
        this.parent.runAfterEach(who, cb)
      else
        cb()
    }, who.threw)
  }

  beforeEach (fn) {
    this.onBeforeEach.push(fn)
  }

  afterEach (fn) {
    this.onAfterEach.push(fn)
  }

  teardown (fn) {
    this.on('teardown', fn)
  }

  shouldAutoend () {
    const should = (
      this.options.autoend &&
      !this.ended &&
      !this.occupied &&
      queueEmpty(this) &&
      !this.pool.length &&
      !this.subtests.length &&
      this.planEnd === -1
    )
    return should
  }

  autoend (value) {
    // set to false to NOT trigger autoend
    if (value === false) {
      this.options.autoend = false
      clearTimeout(this.autoendTimer)
    } else {
      this.options.autoend = true
      this.maybeAutoend()
    }
  }

  maybeAutoend () {
    if (this.shouldAutoend()) {
      clearTimeout(this.autoendTimer)
      this.autoendTimer = setTimeout(() => {
        if (this.shouldAutoend()) {
          clearTimeout(this.autoendTimer)
          this.autoendTimer = setTimeout(() => {
            if (this.shouldAutoend())
              this.end(IMPLICIT)
          })
        }
      })
    }
  }

  endAll (sub) {
    // in the case of the root TAP test object, we might sometimes
    // call endAll on a bailing-out test, as the process is ending
    // In that case, we WILL have a this.occupied and a full queue
    // These cases are very rare to encounter in other Test objs tho
    this.processing = true
    if (this.occupied) {
      const p = this.occupied
      if (p.endAll)
        p.endAll(true)
      else {
        p.parser.abort('test unfinished')
      }
    } else if (sub) {
      this.process()
      if (queueEmpty(this)) {
        const options = Object.assign({}, this.options)
        this.options.at = null
        this.options.stack = ''
        options.test = this.name
        this.fail('test unfinished', options)
      }
    }

    if (this.promise && this.promise.tapAbortPromise)
      this.promise.tapAbortPromise()

    if (this.occupied) {
      this.queue.unshift(this.occupied)
      this.occupied = null
    }

    endAllQueue(this.queue)
    this.processing = false
    this.process()
    this.parser.end()
  }

  get currentAssert () {
    return this[_currentAssert]
  }

  set currentAssert (fn) {
    if (!this[_currentAssert])
      this[_currentAssert] = fn
  }

  pass (message, extra) {
    this.currentAssert = Test.prototype.pass

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    this.printResult(true, message || '(unnamed test)', extra)
    return true
  }

  fail (message, extra) {
    this.currentAssert = Test.prototype.fail

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    this.printResult(false, message || '(unnamed test)', extra)
    return !!(extra.todo || extra.skip)
  }

  ok (obj, message, extra) {
    this.currentAssert = Test.prototype.ok

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}
    message = message || 'expect truthy value'
    return obj ? this.pass(message, extra) : this.fail(message, extra)
  }

  notOk (obj, message, extra) {
    this.currentAssert = Test.prototype.notOk

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}
    message = message || 'expect falsey value'
    return this.ok(!obj, message, extra)
  }

  error (er, message, extra) {
    this.currentAssert = Test.prototype.error

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    if (!er) {
      return this.pass(message || 'should not error', extra)
    }

    if (!(er instanceof Error)) {
      extra.found = er
      return this.fail(message || 'non-Error error encountered', extra)
    }

    message = message || er.message
    extra.found = er
    return this.fail(message, extra)
  }

  equal (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.equal

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should be equal'
    if (found === wanted) {
      return this.pass(message, extra)
    }

    extra.found = found
    extra.wanted = wanted
    extra.compare = '==='

    if (typeof found === 'object' &&
        typeof wanted === 'object' &&
        found &&
        wanted &&
        tsame(found, wanted)) {
      extra.note = 'Objects never === one another'
    }

    return this.fail(message, extra)
  }

  not (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.not

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should not be equal'
    if (found !== wanted) {
      return this.pass(message, extra)
    }

    extra.found = found
    extra.doNotWant = wanted
    extra.compare = '!=='

    return this.fail(message, extra)
  }

  same (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.same

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should be equivalent'
    extra.found = found
    extra.wanted = wanted
    return this.ok(tsame(found, wanted), message, extra)
  }

  notSame (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.notSame

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should not be equivalent'
    extra.found = found
    extra.doNotWant = wanted
    return this.notOk(tsame(found, wanted), message, extra)
  }

  strictSame (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.strictSame

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should be equivalent strictly'
    extra.found = found
    extra.wanted = wanted
    return this.ok(tsame.strict(found, wanted), message, extra)
  }

  strictNotSame (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.strictNotSame

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should not be equivalent strictly'
    extra.found = found
    extra.doNotWant = wanted
    return this.notOk(tsame.strict(found, wanted), message, extra)
  }

  get fullname () {
    const main = process.argv[1] || ''
    return (this.parent ? this.parent.fullname
      : main.indexOf(cwd) === 0 ? main.substr(cwd.length + 1)
      : path.basename(main)) +
      ' ' + (this.name || '').trim()
  }

  matchSnapshot (found, message, extra) {
    this.currentAssert = Test.prototype.matchSnapshot

    if (message && typeof message === 'object')
      extra = message, message = 'must match snapshot'

    if (!extra)
      extra = {}

    // use notOk because snap doesn't return a truthy value
    const m = this.fullname + ' > ' + message
    if (typeof found !== 'string')
      found = util.inspect(found, {
        showHidden: false,
        depth: Infinity
      })

    return this.writeSnapshot
      ? this.notOk(this[_snapshot].snap(found, m),
        message, extra)
      : this.equal(found, this[_snapshot].read(m),
        message, extra)
  }

  match (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.match

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should match pattern provided'
    extra.found = found
    extra.pattern = wanted
    return this.ok(tmatch(found, wanted), message, extra)
  }

  notMatch (found, wanted, message, extra) {
    this.currentAssert = Test.prototype.notMatch

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    message = message || 'should not match pattern provided'
    extra.found = found
    extra.pattern = wanted
    return this.ok(!tmatch(found, wanted), message, extra)
  }

  type (obj, klass, message, extra) {
    this.currentAssert = Test.prototype.type

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    const name = typeof klass === 'function' ?
      klass.name || '(anonymous constructor)'
      : klass

    message = message || 'type is ' + name

    // simplest case, it literally is the same thing
    if (obj === klass) {
      return this.pass(message, extra)
    }

    const tof = typeof obj
    const type = (!obj && tof === 'object') ? 'null'
      // treat as object, but not Object
      // t.type(() => {}, Function)
      : (tof === 'function' &&
        typeof klass === 'function' &&
        klass !== Object) ? 'object'
      : tof

    if (type === 'object' && klass !== 'object') {
      if (typeof klass === 'function') {
        extra.found = Object.getPrototypeOf(obj).constructor.name
        extra.wanted = name
        return this.ok(obj instanceof klass, message, extra)
      }

      // check prototype chain for name
      // at this point, we already know klass is not a function
      // if the klass specified is an obj in the proto chain, pass
      // if the name specified is the name of a ctor in the chain, pass
      for (let p = obj; p; p = Object.getPrototypeOf(p)) {
        const ctor = p.constructor && p.constructor.name
        if (p === klass || ctor === name) {
          return this.pass(message, extra)
        }
      }
    }

    return this.equal(type, name, message, extra)
  }

  throws (_fn, _wanted, _message, _extra) {
    this.currentAssert = Test.prototype.throws

    let fn, wanted, message, extra
    for (let i = 0; i < arguments.length; i++) {
      const arg = arguments[i]
      if (typeof arg === 'function') {
        if (arg === Error || arg.prototype instanceof Error) {
          wanted = arg
        } else if (!fn) {
          fn = arg
        }
      } else if (typeof arg === 'string' && arg) {
        message = arg
      } else if (typeof arg === 'object') {
        if (!wanted) {
          wanted = arg
        } else {
          extra = arg
        }
      }
    }

    if (!extra)
      extra = {}

    if (!message)
      message = fn && fn.name || 'expected to throw'

    if (wanted) {
      if (wanted instanceof Error) {
        const w = {
          message: wanted.message
        }
        if (wanted.name) {
          w.name = wanted.name
        }

        // intentionally copying non-local properties, since this
        // is an Error object, and those are funky.
        for (let i in wanted) {
          w[i] = wanted[i]
        }
        wanted = w

        message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
        extra.wanted = wanted
      }
    }

    if (typeof fn !== 'function') {
      extra.todo = true
      return this.pass(message, extra)
    }

    try {
      fn()
      return this.fail(message, extra)
    } catch (er) {
      // 'name' is a getter.
      if (er.name) {
        Object.defineProperty(er, 'name', {
          value: er.name + '',
          enumerable: true,
          configurable: true,
          writable: true
        })
      }

      const actual = isRegExp(wanted) ? er.message : er
      return wanted ? this.match(actual, wanted, message, extra)
        : this.pass(message, extra)
    }
  }

  doesNotThrow (fn, message, extra) {
    this.currentAssert = Test.prototype.doesNotThrow

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    if (typeof fn === 'string') {
      const x = fn
      fn = message
      message = x
    }

    if (!message) {
      message = fn && fn.name || 'expected to not throw'
    }

    if (typeof fn !== 'function') {
      extra.todo = true
      return this.pass(message, extra)
    }

    try {
      fn()
      return this.pass(message, extra)
    } catch (er) {
      const e = extraFromError(er, extra)
      e.message = er.message
      return this.fail(message, e)
    }
  }

  // like throws, but rejects a returned promise instead
  // also, can pass in a promise instead of a function
  rejects (_fn, _wanted, _message, _extra) {
    this.currentAssert = Test.prototype.rejects

    let fn, wanted, extra, promise, message
    for (let i = 0; i < arguments.length; i++) {
      const arg = arguments[i]
      if (typeof arg === 'function') {
        if (arg === Error || arg.prototype instanceof Error) {
          wanted = arg
        } else if (!fn) {
          fn = arg
        }
      } else if (typeof arg === 'string' && arg) {
        message = arg
      } else if (arg && typeof arg.then === 'function' && !promise) {
        promise = arg
      } else if (typeof arg === 'object') {
        if (!wanted) {
          wanted = arg
        } else {
          extra = arg
        }
      }
    }

    if (!extra)
      extra = {}

    if (!message)
      message = fn && fn.name || 'expect rejected Promise'

    if (wanted) {
      if (wanted instanceof Error) {
        const w = {
          message: wanted.message
        }
        if (wanted.name)
          w.name = wanted.name

        // intentionally copying non-local properties, since this
        // is an Error object, and those are funky.
        for (let i in wanted) {
          w[i] = wanted[i]
        }
        wanted = w

        message += ': ' + (wanted.name || 'Error') + ' ' + wanted.message
        extra.wanted = wanted
      }
    }

    if (!promise && typeof fn !== 'function') {
      extra.todo = true
      this.pass(message, extra)
      return Promise.resolve(this)
    }

    if (!promise)
      promise = fn()

    const textra = {
      buffered: true,
      todo: extra.todo,
      skip: extra.skip
    }

    if (!promise || typeof promise.then !== 'function')
      return this.test(message, textra, t => {
        t.fail(message, extra)
        t.end()
      })

    // have to do as a subtest, because promises are async
    extra.at = stack.at(this.currentAssert)
    return this.test(message, textra, t => promise.then(value => {
      extra.found = value
      t.fail(message, extra)
    }, er => {
      // 'name' is a getter.
      if (er.name) {
        Object.defineProperty(er, 'name', {
          value: er.name + '',
          enumerable: true,
          configurable: true,
          writable: true
        })
      }

      const actual = isRegExp(wanted) ? er.message : er
      return wanted ? t.match(actual, wanted, message, extra)
        : t.pass(message, extra)
    }))
  }

  resolves (promise, message, extra) {
    this.currentAssert = Test.prototype.resolves

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    if (!message)
      message = 'expect resolving Promise'

    if (typeof promise === 'function')
      promise = promise()

    // have to do as a subtest, because promises are async
    extra.at = stack.at(this.currentAssert)

    const textra = {
      buffered: true,
      todo: extra.todo,
      skip: extra.skip
    }

    if (!promise || typeof promise.then !== 'function')
      return this.test(message, textra, t => {
        t.fail(message, extra)
        t.end()
      })

    return this.test(message, textra, t =>
      promise.then(value => {
        extra.found = value
        t.pass(message, extra)
      }))
  }

  resolveMatch (promise, wanted, message, extra) {
    this.currentAssert = Test.prototype.resolveMatch

    if (message && typeof message === 'object')
      extra = message, message = ''

    if (!extra)
      extra = {}

    if (!message)
      message = 'expect resolving Promise'

    // have to do as a subtest, because promises are async
    extra.at = stack.at(this.currentAssert)

    const textra = {
      buffered: true,
      todo: extra.todo,
      skip: extra.skip
    }

    if (!promise || typeof promise.then !== 'function')
      return this.test(message, textra, t => {
        t.fail(message, extra)
        t.end()
      })

    return this.test(message, textra, t =>
      promise.then(value => {
        extra.found = value
        t.match(value, wanted, extra)
      }))
  }
}

const endAllQueue = queue => {
  queue.forEach((p, i) => {
    if ((p instanceof Base) && !p.readyToProcess)
      queue[i] = new TestPoint(false,
        'child test left in queue:' +
        ' t.' + p.constructor.name.toLowerCase() + ' ' + p.name,
        p.options)
  })
  queue.push(['end', IMPLICIT])
}

const queueEmpty = t =>
  t.queue.length === 0 ||
    t.queue.length === 1 && t.queue[0] === 'TAP version 13\n'

Test.prototype.done = Test.prototype.end
Test.prototype.tearDown = Test.prototype.teardown

Object.keys(synonyms)
  .filter(c => Test.prototype[c])
  .forEach(c => synonyms[c].forEach(s =>
    Object.defineProperty(Test.prototype, s, {
      value: Test.prototype[c],
      enumerable: false,
      configurable: true,
      writable: true
    })))

module.exports = Test
Hacker Blog, Shell İndir, Sql İnjection, XSS Attacks, LFI Attacks, Social Hacking, Exploit Bot, Proxy Tools, Web Shell, PHP Shell, Alfa Shell İndir, Hacking Training Set, DDoS Script, Denial Of Service, Botnet, RFI Attacks, Encryption
Telegram @BIBIL_0DAY