231 lines
11 KiB
PowerShell
231 lines
11 KiB
PowerShell
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
Describe "Command Discovery tests" -Tags "CI" {
|
|
|
|
BeforeAll {
|
|
Setup -f testscript.ps1 -Content "'This script should not run. Running from testscript.ps1'"
|
|
Setup -f testscripp.ps1 -Content "'This script should not run. Running from testscripp.ps1'"
|
|
|
|
$TestCasesCommandNotFound = @(
|
|
@{command = 'CommandThatDoesnotExist' ; testName = 'Non-existent command'}
|
|
@{command = 'testscrip?.ps1' ; testName = 'Multiple matches for filename'}
|
|
@{command = "demo" + [System.IO.Path]::DirectorySeparatorChar; testName = 'Non existent command with directory separator'}
|
|
@{command = [System.IO.Path]::DirectorySeparatorChar; testName = 'Directory separator'}
|
|
@{command = 'environment::\path'; testName = 'Provider qualified path'}
|
|
)
|
|
}
|
|
|
|
It "<testName>" -TestCases $TestCasesCommandNotFound {
|
|
param($command)
|
|
{ & $command } | Should -Throw -ErrorId 'CommandNotFoundException'
|
|
}
|
|
|
|
It "Command lookup with duplicate paths" {
|
|
$previousPath = $env:PSModulePath
|
|
|
|
try
|
|
{
|
|
New-Item -Path "$TestDrive\TestFunctionA" -ItemType Directory
|
|
New-Item -Path "$TestDrive\\TestFunctionA\TestFunctionA.psm1" -Value "function TestFunctionA {}" | Out-Null
|
|
|
|
$env:PSModulePath = "$TestDrive" + [System.IO.Path]::PathSeparator + "$TestDrive"
|
|
(Get-Command 'TestFunctionA').count | Should -Be 1
|
|
}
|
|
finally
|
|
{
|
|
$env:PSModulePath = $previousPath
|
|
}
|
|
}
|
|
|
|
It "Alias can be set for a cmdlet" {
|
|
|
|
Set-Alias 'AliasCommandDiscoveryTest' Get-ChildItem
|
|
$commands = (Get-Command 'AliasCommandDiscoveryTest')
|
|
|
|
$commands.Count | Should -Be 1
|
|
$aliasResult = $commands -as [System.Management.Automation.AliasInfo]
|
|
$aliasResult | Should -BeOfType System.Management.Automation.AliasInfo
|
|
$aliasResult.Name | Should -Be 'AliasCommandDiscoveryTest'
|
|
}
|
|
|
|
It "Cyclic aliases - direct" {
|
|
{
|
|
Set-Alias CyclicAliasA CyclicAliasB -Force
|
|
Set-Alias CyclicAliasB CyclicAliasA -Force
|
|
& CyclicAliasA
|
|
} | Should -Throw -ErrorId 'CommandNotFoundException'
|
|
}
|
|
|
|
It "Cyclic aliases - indirect" {
|
|
{
|
|
Set-Alias CyclicAliasA CyclicAliasB -Force
|
|
Set-Alias CyclicAliasB CyclicAliasC -Force
|
|
Set-Alias CyclicAliasC CyclicAliasA -Force
|
|
& CyclicAliasA
|
|
} | Should -Throw -ErrorId 'CommandNotFoundException'
|
|
}
|
|
|
|
It "Get-Command should return only CmdletInfo, FunctionInfo, AliasInfo or FilterInfo" {
|
|
|
|
$commands = Get-Command
|
|
$commands.Count | Should -BeGreaterThan 0
|
|
|
|
foreach($command in $commands)
|
|
{
|
|
$command.GetType().Name | Should -BeIn @("AliasInfo","FunctionInfo","CmdletInfo","FilterInfo")
|
|
}
|
|
}
|
|
|
|
It "Non-existent commands with wildcard should not write errors" {
|
|
Get-Command "CommandDoesNotExist*" -ErrorVariable ev -ErrorAction SilentlyContinue
|
|
$ev | Should -BeNullOrEmpty
|
|
}
|
|
|
|
It "Get- is prepended to commands" {
|
|
(& 'location').Path | Should -Be (Get-Location).Path
|
|
}
|
|
|
|
Context "Use literal path first when executing scripts" {
|
|
BeforeAll {
|
|
$firstFileName = '[test1].ps1'
|
|
$secondFileName = '1.ps1'
|
|
$thirdFileName = '2.ps1'
|
|
$firstResult = "executing $firstFileName in root"
|
|
$secondResult = "executing $secondFileName in root"
|
|
$thirdResult = "executing $thirdFileName in root"
|
|
Setup -f $firstFileName -Content "'$firstResult'"
|
|
Setup -f $secondFileName -Content "'$secondResult'"
|
|
Setup -f $thirdFileName -Content "'$thirdResult'"
|
|
|
|
$subFolder = 'subFolder'
|
|
$firstFileInSubFolder = Join-Path $subFolder -ChildPath $firstFileName
|
|
$secondFileInSubFolder = Join-Path $subFolder -ChildPath $secondFileName
|
|
$thirdFileInSubFolder = Join-Path $subFolder -ChildPath $thirdFileName
|
|
Setup -f $firstFileInSubFolder -Content "'$firstResult'"
|
|
Setup -f $secondFileInSubFolder -Content "'$secondResult'"
|
|
Setup -f $thirdFileInSubFolder -Content "'$thirdResult'"
|
|
|
|
$secondFileSearchInSubfolder = (Join-Path -Path $subFolder -ChildPath '[t1].ps1')
|
|
|
|
$executionWithWildcardCases = @(
|
|
#Region relative paths with './'
|
|
@{command = '.\[test1].ps1' ; expectedResult = $firstResult; name = '.\[test1].ps1'}
|
|
@{command = '.\[t1].ps1' ; expectedResult = $secondResult; name = '.\[t1].ps1'}
|
|
#endregion
|
|
|
|
#Region relative Subfolder paths without './'
|
|
@{command = $secondFileInSubFolder ; expectedResult = $secondResult; name = $secondFileInSubFolder}
|
|
|
|
# Wildcard search is not being performed in this scenario before this change.
|
|
# I noted the issue in the pending message
|
|
@{command = $firstFileInSubFolder ; expectedResult = $firstResult; name = $firstFileInSubFolder; Pending="See note about wildcard in https://github.com/PowerShell/PowerShell/issues/9256"}
|
|
@{command = $secondFileSearchInSubfolder ; expectedResult = $secondResult; name = $secondFileSearchInSubfolder; Pending="See note about wildcard in https://github.com/PowerShell/PowerShell/issues/9256"}
|
|
#endregion
|
|
#Region relative Subfolder paths with '.\'
|
|
@{command = '.\' + $secondFileInSubFolder ; expectedResult = $secondResult; name = $secondFileInSubFolder}
|
|
@{command = '.\subFolder\[test1].ps1' ; expectedResult = $firstResult; name = '.\subFolder\[test1].ps1'}
|
|
@{command = '.\subFolder\[t1].ps1' ; expectedResult = $secondResult; name = '.\' + $secondFileSearchInSubfolder}
|
|
@{command = '.\' + $firstFileInSubFolder ; expectedResult = $firstResult; name = '.\' + $firstFileInSubFolder}
|
|
@{command = '.\' + $secondFileSearchInSubfolder ; expectedResult = $secondResult; name = '.\' + $secondFileSearchInSubfolder}
|
|
#endregion
|
|
|
|
#region rooted paths
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '[test1].ps1') ; expectedResult = $firstResult; name = '.\[test1].ps1 by fully qualified path'}
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '[t1].ps1') ; expectedResult = $secondResult; name = '.\1.ps1 by fully qualified path with wildcard'}
|
|
#endregion
|
|
)
|
|
|
|
$shouldNotExecuteCases = @(
|
|
@{command = 'subFolder\[test1].ps1' ; testName = 'Relative path that where module qualified syntax overlaps'; ExpectedErrorId = 'CouldNotAutoLoadModule'}
|
|
@{command = '.\[12].ps1' ; testName = 'relative path with bracket wildcard matctching multiple files'}
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '[12].ps1') ; testName = 'fully qualified path with bracket wildcard matching multiple files'}
|
|
)
|
|
|
|
Push-Location ${TestDrive}\
|
|
}
|
|
|
|
AfterAll {
|
|
Pop-Location
|
|
}
|
|
|
|
It "Invoking <name> should return '<expectedResult>'" -TestCases $executionWithWildcardCases {
|
|
param($command, $expectedResult, [String]$Pending)
|
|
|
|
if($Pending)
|
|
{
|
|
Set-TestInconclusive -Message $Pending
|
|
}
|
|
|
|
& $command | Should -BeExactly $expectedResult
|
|
}
|
|
|
|
It "'<testName>' should not execute" -TestCases $shouldNotExecuteCases {
|
|
param(
|
|
[string]
|
|
$command,
|
|
[string]
|
|
$ExpectedErrorId = 'CommandNotFoundException'
|
|
)
|
|
{ & $command } | Should -Throw -ErrorId $ExpectedErrorId
|
|
}
|
|
}
|
|
|
|
Context "Get-Command should use globbing first for scripts" {
|
|
BeforeAll {
|
|
$firstResult = '[first script]'
|
|
$secondResult = 'alt script'
|
|
$thirdResult = 'bad script'
|
|
Setup -f '[test1].ps1' -Content "'$firstResult'"
|
|
Setup -f '1.ps1' -Content "'$secondResult'"
|
|
Setup -f '2.ps1' -Content "'$thirdResult'"
|
|
|
|
$gcmWithWildcardCases = @(
|
|
@{command = '.\?[tb]est1?.ps1'; expectedCommand = '[test1].ps1'; expectedCommandCount =1; name = '''.\?[tb]est1?.ps1'''}
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '?[tb]est1?.ps1'); expectedCommand = '[test1].ps1'; expectedCommandCount =1 ; name = '''.\?[tb]est1?.ps1'' by fully qualified path'}
|
|
@{command = '.\[test1].ps1'; expectedCommand = '1.ps1'; expectedCommandCount =1; name = '''.\[test1].ps1'''}
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '[test1].ps1'); expectedCommand = '1.ps1'; expectedCommandCount =1 ; name = '''.\[test1].ps1'' by fully qualified path'}
|
|
@{command = '.\[12].ps1'; expectedCommand = '1.ps1'; expectedCommandCount =0; name = 'relative path with bracket wildcard matctching multiple files'}
|
|
@{command = (Join-Path ${TestDrive} -ChildPath '[12].ps1'); expectedCommand = '1.ps1'; expectedCommandCount =0 ; name = 'fully qualified path with bracket wildcard matctching multiple files'}
|
|
)
|
|
|
|
Push-Location ${TestDrive}\
|
|
}
|
|
|
|
AfterAll {
|
|
Pop-Location
|
|
}
|
|
|
|
It "Get-Command <name> should return <expectedCommandCount> command named '<expectedCommand>'" -TestCases $gcmWithWildcardCases {
|
|
param($command, $expectedCommand, $expectedCommandCount)
|
|
$commands = @(Get-Command -Name $command)
|
|
$commands.Count | Should -Be $expectedCommandCount
|
|
if($expectedCommandCount -gt 0)
|
|
{
|
|
$commands.Name | Should -BeExactly $expectedCommand
|
|
}
|
|
}
|
|
}
|
|
|
|
Context "error cases" {
|
|
It 'Get-Command "less `"-PsPage %db?B of %DoesNotExist:`"" should return nothing' {
|
|
Get-Command -Name "less `"-PsPage %db?B of %DoesNotExist:`"" | Should -BeNullOrEmpty
|
|
}
|
|
|
|
It "Should return command not found for commands in the global scope" {
|
|
{Get-Command -Name 'global:help' -ErrorAction Stop} | Should -Throw -ErrorId 'CommandNotFoundException'
|
|
}
|
|
}
|
|
|
|
Context "Native command discovery" {
|
|
It 'Can discover a native command without extension' {
|
|
$expectedName = if ($IsWindows) { "ping.exe" } else { "ping" }
|
|
(Get-Command -Name "ping" -CommandType Application).Name | Should -Match $expectedName
|
|
}
|
|
|
|
It 'Can discover a native command with extension on Windows' -Skip:(-not $IsWindows) {
|
|
(Get-Command -Name "ping.exe" -CommandType Application).Name | Should -Match "ping.exe"
|
|
}
|
|
}
|
|
}
|