Add tests to language part 1 (#2086)

This commit is contained in:
Yanbing
2016-09-12 10:43:53 -07:00
committed by Sergei Vorobev
parent 1d89d46c76
commit e1bfe97d87
7 changed files with 908 additions and 0 deletions
@@ -0,0 +1,129 @@
Describe "Tests for (error, warning, etc) action preference" -Tags "CI" {
BeforeAll {
$orgin = $GLOBAL:errorActionPreference
}
AfterAll {
if ($GLOBAL:errorActionPreference -ne $orgin)
{
$GLOBAL:errorActionPreference = $orgin
}
}
Context 'Setting ErrorActionPreference to stop prevents user from getting the error exception' {
$err = $null
try
{
get-childitem nosuchfile.nosuchextension -ea stop -ev err
}
catch {}
It '$err.Count' { $err.Count | Should Be 1 }
It '$err[0] should not be $null' { $err[0] | Should Not Be $null }
It '$err[0].GetType().Name' { $err[0].GetType().Name | Should Be ActionPreferenceStopException }
It '$err[0].ErrorRecord' { $err[0].ErrorRecord | Should not BeNullOrEmpty }
It '$err[0].ErrorRecord.Exception.GetType().Name' { $err[0].ErrorRecord.Exception.GetType().Name | Should Be ItemNotFoundException }
}
It 'ActionPreference Ignore Works' {
$errorCount = $error.Count
Get-Process -Name asdfasdfsadfsadf -ErrorAction Ignore
$error.Count | Should Be $errorCount
}
It 'action preference of Ignore cannot be set as a preference variable' {
try {
$GLOBAL:errorActionPreference = "Ignore"
Get-Process -Name asdfasdfasdf
Throw "Exception expected, execution should not have reached here"
} catch {
$_.CategoryInfo.Reason | Should Be NotSupportedException
} finally {
$GLOBAL:errorActionPreference = $orgin
}
}
It 'action preference of Suspend cannot be set as a preference variable' {
try {
$GLOBAL:errorActionPreference = "Suspend"
Get-Process -Name asdfasdfasdf
Throw "Exception expected, execution should not have reached here"
} catch {
$_.CategoryInfo.Reason | Should Be ArgumentTransformationMetadataException
}
finally {
$GLOBAL:errorActionPreference = $orgin
}
}
It 'enum disambiguation works' {
$errorCount = $error.Count
Get-Process -Name asdfasdfsadfsadf -ErrorAction Ig
$error.Count | Should Be $errorCount
}
It 'ErrorAction = Suspend works on Workflow' -Skip:$IsCoreCLR {
. .\TestsOnWinFullOnly.ps1
Run-TestOnWinFull "ActionPreference:ErrorAction=SuspendOnWorkflow"
}
It 'ErrorAction = Suspend does not work on functions' {
function MyHelperFunction {
[CmdletBinding()]
param()
"Hello"
}
try
{
MyHelperFunction -ErrorAction Suspend
Throw "Exception expected, execution should not have reached here"
} catch {
$_.FullyQualifiedErrorId | Should Be "ParameterBindingFailed,MyHelperFunction"
}
}
It 'ErrorAction = Suspend does not work on cmdlets' {
try
{
Get-Process -ErrorAction Suspend
Throw "Exception expected, execution should not have reached here"
}
catch {
$_.FullyQualifiedErrorId | Should Be "ParameterBindingFailed,Microsoft.PowerShell.Commands.GetProcessCommand"
}
}
It 'WarningAction = Suspend does not work' {
try
{
Get-Process -WarningAction Suspend
Throw "Exception expected, execution should not have reached here"
}
catch {
$_.FullyQualifiedErrorId | Should Be "ParameterBindingFailed,Microsoft.PowerShell.Commands.GetProcessCommand"
}
}
#issue 2076
It 'ErrorAction and WarningAction are the only action preferences do not support suspend' -Pending{
$params = [System.Management.Automation.Internal.CommonParameters].GetProperties().Name | Select-String Action
$suspendErrors = $null
$num=0
$params | % {
$input=@{'InputObject' = 'Test';$_='Suspend'}
try {
Write-Output @input
} catch {
$_.FullyQualifiedErrorId | Should Be "ParameterBindingFailed,Microsoft.PowerShell.Commands.WriteOutputCommand"
$num++
}
}
$num | Should Be 2
}
}
@@ -0,0 +1,110 @@
Describe "Test restricted language check method on scriptblocks" -Tags "CI" {
BeforeAll {
set-strictmode -v 2
function list {
$l = [System.Collections.Generic.List[String]]::new()
$args | foreach {$l.Add($_)}
, $l
}
}
AfterAll {
Set-StrictMode -Off
}
It 'Check basic expressions' {
{{2+2}.CheckRestrictedLanguage($null, $null, $false) } | Should Not Throw # Succeed with no variables
}
It 'Check default variables' {
{{ $PSCulture, $PSUICulture, $true, $false, $null}.CheckRestrictedLanguage($null, $null, $false) } | Should Not Throw
}
It 'Check default variables' {
try
{
{2+$a}.CheckRestrictedLanguage($null, $null, $false)
Throw "Exception expected, execution should not have reached here"
}
catch
{
$_.FullyQualifiedErrorId | Should Be 'ParseException'
}
}
It 'Check union of default + one allowed variables' {
{ { 2 + $a }.CheckRestrictedLanguage($null, (list a), $false) }| Should Not Throw # succeed
}
It 'Check union of default + two allowed variables' {
{ { $a + $b }.CheckRestrictedLanguage($null, (list a b), $false) } | Should Not Throw # succeed
}
It 'Check union of default + allowed variables' {
{ { $PSCulture, $PSUICulture, $true, $false, $null, $a, $b}.CheckRestrictedLanguage($null, (list a b), $false) }| Should Not Throw
}
It 'Check union of default + one disallowed variables' {
try
{
{ $a + $b + $c }.CheckRestrictedLanguage($null, (list a b), $false) # fail
Throw "Exception expected, execution should not have reached here"
}
catch
{
$_.FullyQualifiedErrorId | Should Be 'ParseException'
}
}
It 'Check union of default + one allowed variable and but not allow environment variable' {
try
{
{ 2 + $a + $env:foo }.CheckRestrictedLanguage($null, (list a), $false) # fail
Throw "Exception expected, execution should not have reached here"
}
catch
{
$_.FullyQualifiedErrorId | Should Be 'ParseException'
}
}
It 'Check union of default + one allowed variable name and allow environment variable ' {
{{ 2 + $a + $env:foo }.CheckRestrictedLanguage($null, (list a), $true)} | Should Not Throw # succeed
}
It 'Check that wildcard allows env even if the flag is set to false' {
{ { 2 + $a + $b + $c + $env:foo }.CheckRestrictedLanguage($null, (list *), $false)} | Should Not Throw # succeed
}
It 'Check for restricted commands' {
try
{
{get-date}.CheckRestrictedLangauge($null, $null, $false)
Throw "Exception expected, execution should not have reached here"
}
catch
{
$_.FullyQualifiedErrorId | Should Be 'MethodNotFound'
}
}
It 'Check for allowed commands and variables' {
{ { get-process | where name -match $pattern | foreach $prop }.CheckRestrictedLanguage(
(list get-process where foreach),
(list prop pattern)
, $false) }| Should Not Throw
}
}
@@ -0,0 +1,121 @@
Describe "Cmdlet declaration statement" -Tags "CI" {
$testData = @(
@{ Name = 'Verify non-cmdlet formatted names are allowed';
Script = '
function foo
{
[CmdletBinding()]
param()
$a
}' },
@{ Name = 'Valid cmdlet names case 1';
Script = '
function foo
{
[CmdletBinding()]
param()
$a
}' },
@{ Name = 'Valid cmdlet names case 2';
Script = '
function get-foo
{
[CmdletBinding()]
param()
$a
}' },
@{ Name = 'Valid cmdlet names case 3';
Script = '
{
[CmdletBinding()]
param()
$a
}' },
@{
Name ='Using parameter annotation in script cmdlets';
Script = '
function get-foo
{
param([Parameter(mandatory=$true)]$a)
$a
}'},
@{
Name = 'Cmdlet declaration parameter: should process';
Script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true)]
param([Parameter(mandatory=$true)]$a)
$a
}' },
@{
Name = 'Cmdlet declaration parameter: confirm impact';
Script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="low")]
param([Parameter(mandatory=$true)]$a)
$a
}'},
@{
Name = 'Cmdlet declaration parameter: defaultparametersetname';
Script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="low", defaultparametersetname="set1")]
param([Parameter(mandatory=$true)]$a)
$a
}'},
@{
Name = 'cmdlet declaration within as cmdlet';
Script = '
function get-foo {
[CmdletBinding()]
param()
function get-bar
{
param([Parameter(mandatory=$true)]$a)
$a
}
}'}
@{
Name = 'cmdlet declaration within scriptblock';
Script = '
{
param([Parameter(mandatory=$true)]$a)
$a
}'},
@{
Name = 'cmdlet declaration within scriptblock 2';
Script = '
{
param([Parameter(mandatory=$true)]$a)
$a
}'},
@{
Name = 'cmdlet declaration within scriptblock 3';
Script = '
{
[CmdletBinding(SupportsShouldProcess=$true)]
param([Parameter(mandatory=$true)]$a)
$a
}'})
It '<Name>' -TestCases $testData {
param($Name, $script)
$syntaxerrors = $null
$null = [system.management.automation.psparser]::tokenize($script, [ref] $syntaxerrors)
#Error should not be reported
$syntaxerrors.Count | Should Be 0
}
}
@@ -0,0 +1,373 @@
Describe "Common parameters support for script cmdlets" -Tags "CI" {
BeforeEach {
$rs = [system.management.automation.runspaces.runspacefactory]::CreateRunspace()
$rs.open()
$ps = [System.Management.Automation.PowerShell]::Create()
$ps.Runspace = $rs
}
AfterEach {
$ps.Dispose()
$rs.Dispose()
}
Context "Debug" {
BeforeAll {
$script = "
function get-foo
{
[CmdletBinding()]
param()
write-output 'output foo'
write-debug 'debug foo'
}"
}
It "Debug get-foo" {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should be "output foo"
$ps.Streams.Debug.Count | Should Be 0
}
It 'get-foo -debug' {
$command = 'get-foo -debug'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.Streams.Debug[0].Message | Should Be "debug foo"
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
Context "verbose" {
BeforeAll {
$script = "
function get-foo
{
[CmdletBinding()]
param()
write-output 'output foo'
write-verbose 'verbose foo'
}"
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.streams.verbose.Count | Should Be 0
}
It 'get-foo -verbose' {
$command = 'get-foo -verbose'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.Streams.verbose[0].Message | Should Be "verbose foo"
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
Context "erroraction" {
BeforeAll {
$script = "
function get-foo
{
[CmdletBinding()]
param()
write-error 'error foo'
write-output 'output foo'
}"
}
It 'erroraction' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.Streams.error[0].ToString() | Should match "error foo"
}
It 'erroraction continue' {
$command = 'get-foo -erroraction Continue'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.Streams.error[0].ToString() | Should match "error foo"
}
It 'erroraction SilentlyContinue' {
$command = 'get-foo -erroraction SilentlyContinue'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be "output foo"
$ps.streams.error.count | Should Be 0
}
It 'erroraction Stop' {
$command = 'get-foo -erroraction Stop'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
try
{
$ps.EndInvoke($asyncResult)
Throw "Exception expected, execution should not have reached here"
}
catch {
$_.FullyQualifiedErrorId | Should Be "ActionPreferenceStopException"
} # Exception: "Command execution stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: error foo"
# BUG in runspace api.
#$ps.error.count | Should Be 1
$ps.InvocationStateInfo.State | Should Be 'Failed'
}
}
Context "SupportShouldprocess" {
$script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true)]
param()
if($pscmdlet.shouldprocess("foo", "foo action"))
{
write-output "foo action"
}
}'
It 'SupportShouldprocess' {
$command = 'get-foo'
$ps = [system.management.automation.powershell]::Create()
[void] $ps.AddScript($script + $command)
$ps.RunspacePool = $rp
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be 'foo action'
}
It 'shouldprocess support -whatif' {
$command = 'get-foo -whatif'
$ps = [system.management.automation.powershell]::Create()
[void] $ps.AddScript($script + $command)
$ps.RunspacePool = $rp
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
It 'shouldprocess support -confirm under the non-interactive host' {
$command = 'get-foo -confirm'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
Context 'confirmimpact support: none' {
BeforeAll {
$script = '
function get-foo
{
[CmdletBinding(supportsshouldprocess=$true, ConfirmImpact="none")]
param()
if($pscmdlet.shouldprocess("foo", "foo action"))
{
write-output "foo action"
}
}'
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be 'foo action'
}
It 'get-foo -confirm' {
$command = 'get-foo -confirm'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be 'foo action'
}
}
Context 'confirmimpact support: low under the non-interactive host' {
BeforeAll {
$script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="low")]
param()
if($pscmdlet.shouldprocess("foo", "foo action"))
{
write-output "foo action"
}
}'
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be 'foo action'
}
It 'get-foo -confirm' {
$command = 'get-foo -confirm'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
Context 'confirmimpact support: Medium under the non-interactive host' {
BeforeAll {
$script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="medium")]
param()
if($pscmdlet.shouldprocess("foo", "foo action"))
{
write-output "foo action"
}
}'
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$output = $ps.EndInvoke($asyncResult)
$output[0] | Should Be 'foo action'
}
It 'get-foo -confirm' {
$command = 'get-foo -confirm'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
Context 'confirmimpact support: High under the non-interactive host' {
BeforeAll {
$script = '
function get-foo
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="high")]
param()
if($pscmdlet.shouldprocess("foo", "foo action"))
{
write-output "foo action"
}
}'
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
It 'get-foo -confirm' {
$command = 'get-foo -confirm'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should be 'Completed'
}
}
Context 'ShouldContinue Support under the non-interactive host' {
BeforeAll {
$script = '
function get-foo
{
[CmdletBinding()]
param()
if($pscmdlet.shouldcontinue("foo", "foo action"))
{
write-output "foo action"
}
}'
}
It 'get-foo' {
$command = 'get-foo'
[void] $ps.AddScript($script + $command)
$asyncResult = $ps.BeginInvoke()
$ps.EndInvoke($asyncResult)
$ps.Streams.Error.Count | Should Be 1 # the host does not implement it.
$ps.InvocationStateInfo.State | Should Be 'Completed'
}
}
}
@@ -0,0 +1,106 @@
Describe 'Test for conversion b/w script block and delegate' -Tags "CI" {
BeforeAll {
function lineno
{
$myInvocation.ScriptLineNumber
}
function Generate-ArgumentTypesAndParameters
{
param([int] $num, [ref] $parameters, [ref]$argumentTypes, [bool]$hasReturn = $false)
For($j = 1; $j -le $num; $j++)
{
$ran = Get-Random -Minimum 1 -Maximum 3
$type = [Int32]
switch ($ran)
{
1 { $type = [Int32]; break}
2 { $type = [string]; break}
3 { $type = [Hashtable]; break}
}
$argumentTypes.Value += $type;
if((-not $hasReturn) -or ($j -lt $num ) ) {
$parameters.Value += Get-Value($type)
}
}
}
function Get-Value
{
param([type] $t)
if ($t -eq [Int32]) { 100 }
elseif($t -eq [string]) { 'abc' }
elseif ($t -eq [Hashtable]) {@{a = 'foo'} }
}
}
#0 arg, no return
It 'System.Action' {
([System.Action]{ $script:gl=lineno; $args.Length | Should Be 0 }).Invoke()
($gl + 1) | Should Be (lineno)
}
# multiple args, no return
For($i = 1; $i -le 8; $i++)
{
$str = 'System.Action`{0}' -f $i
Context $str {
$gt = [object].Assembly.GetType($str)
$parameters = @()
$argumentTypes=@()
Generate-ArgumentTypesAndParameters $i ([ref] $parameters) ([ref] $argumentTypes)
$ct = $gt.MakeGenericType($argumentTypes)
$func = { $script:gl=lineno; $args.Length | Should Be $i } -as $ct
$func.DynamicInvoke($parameters)
It '$gl + 2' { ($gl + 2) | Should Be (lineno) }
}
}
#0 arg with return value
It 'System.Func[Int32]' {
([System.Func[Int32]]{ $script:gl=lineno; $args.Length }).Invoke() | Should Be 0
($gl + 1) | Should Be (lineno)
}
It 'System.Func[string]' {
([System.Func[string]]{ $script:gl=lineno; 'hello' }).Invoke() | Should Be 'hello'
($gl + 1) | Should Be (lineno)
}
It 'System.Func[hashtable]' {
(([System.Func[hashtable]]{ $script:gl=lineno; @{a = 'foo' }}).Invoke()).a | Should Be 'foo'
($gl + 1) | Should Be (lineno)
}
#multiple args, differnt return type
For($i = 2; $i -le 9; $i++)
{
$str = 'System.Func`{0}' -f $i
Context $str {
$gt = [object].Assembly.GetType($str)
$parameters = @()
$argumentTypes=@()
Generate-ArgumentTypesAndParameters $i ([ref] $parameters) ([ref] $argumentTypes) $true
$v= Get-Value($argumentTypes[$i-1])
$ct = $gt.MakeGenericType($argumentTypes)
$func = { $script:gl=lineno; $null = ($args.Length | Should Be ($i-1)); $v } -as $ct
$t = $func.DynamicInvoke($parameters)
It '$gl + 2' { ($gl + 2) | Should Be (lineno) }
if ($argumentTypes[$i-1] -eq [Hashtable] )
{
It '$t.a' { $t.a | Should Be $v.a }
}
else
{
It '$t' { $t | Should Be $v }
}
}
}
}
@@ -0,0 +1,39 @@
Describe "Parallel foreach syntax" -Tags "CI" {
Context 'Should be able to retrieve AST of parallel foreach, error in regular case' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($foo in $bar) {}', [ref] $null, [ref] $errors)
It '$errors.Count' { $errors.Count | Should Be 1 }
It '$ast.EndBlock.Statements[0].Flags' { $ast.EndBlock.Statements[0].Flags | Should Be 'Parallel' }
}
It 'Should be able to retrieve AST of parallel foreach, works in JobDefinition case' -Skip:$IsCoreCLR {
. .\TestsOnWinFullOnly.ps1
Run-TestOnWinFull "ForeachParallel:ASTOfParallelForeachOnWorkflow"
}
Context 'Supports newlines before and after' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
"foreach `n-parallel `n(`$foo in `$bar) {}", [ref] $null, [ref] $null)
It '$errors.Count' { $errors.Count | Should Be 0 }
It '$ast.EndBlock.Statements[0].Flags' { $ast.EndBlock.Statements[0].Flags | Should Be 'Parallel' }
}
Context 'Generates an error on invalid parameter' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -bogus ($input in $bar) { }', [ref]$null, [ref]$errors)
It '$errors.Count' { $errors.Count | Should Be 1 }
It '$errors[0].ErrorId' { $errors[0].ErrorId | Should Be InvalidForeachFlag }
}
Context 'Generate an error on -parallel that is not a workflow' {
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'foreach -parallel ($input in $bar) { }', [ref]$null, [ref]$errors)
It '$errors.Count' { $errors.Count | Should Be 1 }
It '$errors[0].ErrorId' { $errors[0].ErrorId | Should Be ParallelNotSupported }
}
}
@@ -0,0 +1,30 @@
function Run-TestOnWinFull
{
[CmdletBinding()]
param( [string]$name )
switch ($name)
{
"ActionPreference:ErrorAction=SuspendOnWorkflow" {
workflow TestErrorActionSuspend { "Hello" }
$r = TestErrorActionSuspend -ErrorAction Suspend
$r | Should Be Hello
break; }
"ForeachParallel:ASTOfParallelForeachOnWorkflow" {
Import-Module PSWorkflow
$errors = @()
$ast = [System.Management.Automation.Language.Parser]::ParseInput(
'workflow foo { foreach -parallel ($foo in $bar) {} }', [ref] $null, [ref] $errors)
$errors.Count | Should Be 0
$ast.EndBlock.Statements[0].Body.EndBlock.Statements[0].Flags | Should Be 'Parallel'
break;
}
default {
#do nothing
}
}
}