main
  1// Copyright 2021 Google LLC
  2//
  3// Licensed under the Apache License, Version 2.0 (the "License");
  4// you may not use this file except in compliance with the License.
  5// You may obtain a copy of the License at
  6//
  7//     https://www.apache.org/licenses/LICENSE-2.0
  8//
  9// Unless required by applicable law or agreed to in writing, software
 10// distributed under the License is distributed on an "AS IS" BASIS,
 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12// See the License for the specific language governing permissions and
 13// limitations under the License.
 14
 15import assert from 'node:assert'
 16import { test, describe } from 'node:test'
 17import process from 'node:process'
 18import '../../build/globals.js'
 19
 20const _describe = process.platform === 'win32' ? describe : describe.skip
 21
 22const _testPwsh = which.sync('pwsh', { nothrow: true }) ? test : test.skip
 23
 24_describe('win32', () => {
 25  test('should work with windows-specific commands', async () => {
 26    const p = await $`echo $0` // Bash is first by default.
 27    assert.match(p.stdout, /bash/)
 28
 29    await within(async () => {
 30      usePowerShell()
 31      assert.match($.shell, /powershell/i)
 32      const p = await $`get-host`
 33      assert.match(p.stdout, /PowerShell/)
 34    })
 35  })
 36
 37  test('quotePowerShell works', async () => {
 38    await within(async () => {
 39      usePowerShell()
 40      const p = await $`echo ${`Windows 'rulez!'`}`
 41      assert.match(p.stdout, /Windows 'rulez!'/)
 42    })
 43  })
 44
 45  _testPwsh('should work with pwsh when it is available', async () => {
 46    await within(async () => {
 47      usePwsh()
 48      assert.match($.shell, /pwsh/i)
 49      const p = await $`echo 'Hello,' && echo ${`new 'PowerShell'!`}`
 50      assert.match(p.stdout, /Hello,\s+new 'PowerShell'!/)
 51    })
 52  })
 53
 54  test('should create a dir via mkdir', async () => {
 55    const temp = tmpdir()
 56    const _$ = $({ verbose: true, cwd: temp })
 57
 58    console.log('shell:', $.shell)
 59    await _$`which bash`
 60    await _$`bash --version`
 61
 62    await _$`mkdir -p ${path.join(temp, 'AA-zx-test')}`
 63    await _$`mkdir -p BB-zx-test`
 64    const { stdout } = await _$`ls -l | grep zx-test`
 65
 66    assert.match(stdout, /AA-zx-test/)
 67    assert.match(stdout, /BB-zx-test/)
 68  })
 69
 70  test('ps detects self process', async () => {
 71    const [root] = await ps.lookup({ pid: process.pid })
 72    assert.equal(root.pid, process.pid)
 73  })
 74
 75  test('kill works', async () => {
 76    const p = $({ nothrow: true })`sleep 100`
 77    const { pid } = p
 78    const found = await ps.lookup({ pid })
 79    console.log('found:', found)
 80    assert.equal(found.length, 1)
 81    assert.equal(found[0].pid, pid)
 82
 83    await p.kill()
 84    const killed = await ps.lookup({ pid })
 85    console.log('killed:', killed)
 86    assert.equal(killed.length, 0)
 87  })
 88
 89  test('abort controller works', async () => {
 90    const ac = new AbortController()
 91    const { signal } = ac
 92    const p = $({
 93      signal,
 94      timeout: '5s',
 95      nothrow: true,
 96      killSignal: 'SIGKILL',
 97    })`sleep 10`
 98
 99    setTimeout(async () => {
100      assert.throws(
101        () => p.abort('SIGINT'),
102        /signal is controlled by another process/
103      )
104      setTimeout(() => {
105        ac.abort('stop')
106      }, 500)
107    }, 500)
108
109    const o = await p
110    assert.equal(o.signal, 'SIGTERM')
111    assert.throws(() => p.abort(), /Too late to abort the process/)
112    assert.throws(() => p.kill(), /Too late to kill the process/)
113  })
114})