mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 20:56:02 +00:00
Also remove a couple of language tests which were actually duplicated Change the one loop which loops through test cases to include an iteration number to remove test name duplication
176 lines
5.1 KiB
PowerShell
176 lines
5.1 KiB
PowerShell
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
# Licensed under the MIT License.
|
|
#
|
|
# Run the new parser, return either errors or the ast
|
|
#
|
|
|
|
function Get-ParseResults
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ValueFromPipeline=$True,Mandatory=$True)]
|
|
[string]$src,
|
|
[switch]$Ast
|
|
)
|
|
|
|
$errors = $null
|
|
$result = [System.Management.Automation.Language.Parser]::ParseInput($src, [ref]$null, [ref]$errors)
|
|
if ($Ast) { $result } else { ,$errors }
|
|
}
|
|
|
|
#
|
|
# Run script and return errors
|
|
#
|
|
function Get-RuntimeError
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(ValueFromPipeline=$True,Mandatory=$True)][string]$src
|
|
)
|
|
|
|
$errors = $null
|
|
try
|
|
{
|
|
[scriptblock]::Create($src).Invoke() > $null
|
|
}
|
|
catch
|
|
{
|
|
return $_.Exception.InnerException.ErrorRecord
|
|
}
|
|
}
|
|
|
|
function position_message
|
|
{
|
|
param($position)
|
|
|
|
if ($position.Line.Length -lt $position.ColumnNumber)
|
|
{
|
|
$position.Line + " <<<<"
|
|
}
|
|
else
|
|
{
|
|
$position.Line.Insert($position.ColumnNumber, " <<<<")
|
|
}
|
|
}
|
|
|
|
#
|
|
# Pester friendly version of Test-Error
|
|
#
|
|
function ShouldBeParseError
|
|
{
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$src,
|
|
[string[]]$expectedErrors,
|
|
[int[]]$expectedOffsets,
|
|
# This is a temporary solution after moving type creation from parse time to runtime
|
|
[switch]$SkipAndCheckRuntimeError,
|
|
# for test coverarage purpose, tests validate columnNumber or offset
|
|
[switch]$CheckColumnNumber
|
|
)
|
|
|
|
Context "Parse error expected: <<$src>>" {
|
|
# Test case error if this fails
|
|
$expectedErrors.Count | Should Be $expectedOffsets.Count
|
|
|
|
if ($SkipAndCheckRuntimeError)
|
|
{
|
|
It "error should happen at parse time, not at runtime" -Skip {}
|
|
$errors = Get-RuntimeError -Src $src
|
|
# for runtime errors we will only get the first one
|
|
$expectedErrors = ,$expectedErrors[0]
|
|
$expectedOffsets = ,$expectedOffsets[0]
|
|
}
|
|
else
|
|
{
|
|
$errors = Get-ParseResults -Src $src
|
|
}
|
|
|
|
It "Error count" { $errors.Count | Should Be $expectedErrors.Count }
|
|
for ($i = 0; $i -lt $errors.Count; ++$i)
|
|
{
|
|
$err = $errors[$i]
|
|
|
|
if ($SkipAndCheckRuntimeError)
|
|
{
|
|
$errorId = $err.FullyQualifiedErrorId
|
|
}
|
|
else
|
|
{
|
|
$errorId = $err.ErrorId
|
|
}
|
|
It "Error Id (iteration:$i)" { $errorId | Should Be $expectedErrors[$i] }
|
|
$acutalPostion = $err.Extent.StartScriptPosition.Offset
|
|
if ( $CheckColumnNumber ) { $acutalPostion = $err.Extent.StartScriptPosition.ColumnNumber }
|
|
It "Error position (iteration:$i)" -Pending:$SkipAndCheckRuntimeError { $acutalPostion | Should Be $expectedOffsets[$i] }
|
|
}
|
|
}
|
|
}
|
|
|
|
function Flatten-Ast
|
|
{
|
|
[CmdletBinding()]
|
|
param([System.Management.Automation.Language.Ast] $ast)
|
|
|
|
$ast
|
|
$ast | gm -type property | Where-Object { ($prop = $_.Name) -ne 'Parent' } | ForEach-Object {
|
|
$ast.$prop | Where-Object { $_ -is [System.Management.Automation.Language.Ast] } | ForEach-Object { Flatten-Ast $_ }
|
|
}
|
|
}
|
|
|
|
function Test-ErrorStmt
|
|
{
|
|
param([string]$src, [string]$errorStmtExtent)
|
|
$a = $args
|
|
Context "Error Statement expected: <<$src>>" {
|
|
$ast = Get-ParseResults $src -Ast
|
|
$asts = @(Flatten-Ast $ast.EndBlock.Statements[0])
|
|
|
|
It 'Type is ErrorStatementAst' { $asts[0] | Should BeOfType System.Management.Automation.Language.ErrorStatementAst }
|
|
It "`$asts.count" { $asts.Count | Should Be ($a.Count + 1) }
|
|
It "`$asts[0].Extent.Text" { $asts[0].Extent.Text | Should Be $errorStmtExtent }
|
|
for ($i = 0; $i -lt $a.Count; ++$i)
|
|
{
|
|
It "`$asts[$($i + 1)].Extent.Text" { $asts[$i + 1].Extent.Text | Should Be $a[$i] }
|
|
}
|
|
}
|
|
}
|
|
|
|
function Test-Ast
|
|
{
|
|
param([string]$src)
|
|
$a = $args
|
|
$ast = Get-ParseResults $src -Ast
|
|
$asts = @(Flatten-Ast $ast)
|
|
Context "Ast Validation: <<$src>>" {
|
|
It "`$asts.count" { $asts.Count | Should Be $a.Count }
|
|
for ($i = 0; $i -lt $a.Count; ++$i)
|
|
{
|
|
It "`$asts[$i].Extent.Text" { $asts[$i].Extent.Text | Should Be $a[$i] }
|
|
}
|
|
}
|
|
}
|
|
|
|
## ErrorStatement is special for SwitchStatement
|
|
function Test-ErrorStmtForSwitchFlag
|
|
{
|
|
param([string]$src, [string]$flagName)
|
|
$a = $args
|
|
$ast = Get-ParseResults $src -Ast
|
|
$ast = $ast.EndBlock.Statements[0]
|
|
Context "Ast Validation: <<$src>>" {
|
|
$ast | Should BeOfType System.Management.Automation.Language.ErrorStatementAst
|
|
$ast.Flags.ContainsKey($flagName) | Should be $true
|
|
|
|
$asts = @(Flatten-Ast $ast.Flags[$flagName].Item2)
|
|
|
|
$asts.Count | Should Be $a.Count
|
|
for ($i = 0; $i -lt $a.Count; ++$i)
|
|
{
|
|
$asts[$i].Extent.Text | Should Be $a[$i]
|
|
}
|
|
}
|
|
}
|
|
|
|
Export-ModuleMember -Function Test-ErrorStmt, Test-Ast, ShouldBeParseError, Get-ParseResults, Get-RuntimeError, Test-ErrorStmtForSwitchFlag
|