From d28f8cce70f27e95dee63ac2f5bfaf50afb4d489 Mon Sep 17 00:00:00 2001 From: kborle Date: Tue, 17 Nov 2015 16:26:55 -0800 Subject: [PATCH 1/6] Renames CustomizedRulePath parameter and modifies its behavior. * Renames CustomizedRulePath parameter to CustomRulePath. * Adds CustromizedRulePath as an alias of CustomRulePath. * Adds RecurseCustomRulePath switch to recursively retrieve custom rules. * Fixes a bug: CustomRulePath can now accept paths with a trailing backslash. * CustomRulePath parameter now takes only one string, instead of an array of strings. --- .../Commands/GetScriptAnalyzerRuleCommand.cs | 25 +++++-- .../Commands/InvokeScriptAnalyzerCommand.cs | 26 +++++-- Engine/Helper.cs | 37 ++++++++++ Engine/ScriptAnalyzer.cs | 10 +-- Tests/Engine/CustomizedRule.tests.ps1 | 73 ++++++++++++++++++- Tests/Engine/GetScriptAnalyzerRule.tests.ps1 | 8 +- Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 16 ++-- Tests/Engine/LibraryUsage.tests.ps1 | 8 +- Tests/Engine/samplerule/samplerule1.psm1 | 47 ++++++++++++ .../samplerule/samplerule2/samplerule2.psm1 | 47 ++++++++++++ .../samplerule2/samplerule3/samplerule3.psm1 | 47 ++++++++++++ 11 files changed, 315 insertions(+), 29 deletions(-) create mode 100644 Tests/Engine/samplerule/samplerule1.psm1 create mode 100644 Tests/Engine/samplerule/samplerule2/samplerule2.psm1 create mode 100644 Tests/Engine/samplerule/samplerule2/samplerule3/samplerule3.psm1 diff --git a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs index a914e1f59..f9c1934bc 100644 --- a/Engine/Commands/GetScriptAnalyzerRuleCommand.cs +++ b/Engine/Commands/GetScriptAnalyzerRuleCommand.cs @@ -33,12 +33,25 @@ public class GetScriptAnalyzerRuleCommand : PSCmdlet, IOutputWriter [Parameter(Mandatory = false)] [ValidateNotNullOrEmpty] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public string[] CustomizedRulePath + [Alias("CustomizedRulePath")] + public string CustomRulePath { - get { return customizedRulePath; } - set { customizedRulePath = value; } + get { return customRulePath; } + set { customRulePath = value; } } - private string[] customizedRulePath; + private string customRulePath; + + /// + /// RecurseCustomRulePath: Find rules within subfolders under the path + /// + [Parameter(Mandatory = false)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public SwitchParameter RecurseCustomRulePath + { + get { return recurseCustomRulePath; } + set { recurseCustomRulePath = value; } + } + private bool recurseCustomRulePath; /// /// Name: The name of a specific rule to list. @@ -76,7 +89,9 @@ public string[] Severity /// protected override void BeginProcessing() { - ScriptAnalyzer.Instance.Initialize(this, customizedRulePath); + string[] rulePaths = Helper.ProcessCustomRulePaths(customRulePath, + this.SessionState, recurseCustomRulePath); + ScriptAnalyzer.Instance.Initialize(this, rulePaths); } /// diff --git a/Engine/Commands/InvokeScriptAnalyzerCommand.cs b/Engine/Commands/InvokeScriptAnalyzerCommand.cs index ccf5d5992..afbfc46b7 100644 --- a/Engine/Commands/InvokeScriptAnalyzerCommand.cs +++ b/Engine/Commands/InvokeScriptAnalyzerCommand.cs @@ -73,12 +73,25 @@ public string ScriptDefinition [Parameter(Mandatory = false)] [ValidateNotNull] [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - public string[] CustomizedRulePath + [Alias("CustomizedRulePath")] + public string CustomRulePath { - get { return customizedRulePath; } - set { customizedRulePath = value; } + get { return customRulePath; } + set { customRulePath = value; } } - private string[] customizedRulePath; + private string customRulePath; + + /// + /// RecurseCustomRulePath: Find rules within subfolders under the path + /// + [Parameter(Mandatory = false)] + [SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] + public SwitchParameter RecurseCustomRulePath + { + get { return recurseCustomRulePath; } + set { recurseCustomRulePath = value; } + } + private bool recurseCustomRulePath; /// /// ExcludeRule: Array of names of rules to be disabled. @@ -164,9 +177,12 @@ public string Profile /// protected override void BeginProcessing() { + string[] rulePaths = Helper.ProcessCustomRulePaths(customRulePath, + this.SessionState, recurseCustomRulePath); + ScriptAnalyzer.Instance.Initialize( this, - customizedRulePath, + rulePaths, this.includeRule, this.excludeRule, this.severity, diff --git a/Engine/Helper.cs b/Engine/Helper.cs index bc2fef74c..ef10cefc5 100644 --- a/Engine/Helper.cs +++ b/Engine/Helper.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Management.Automation; @@ -983,9 +984,45 @@ public Tuple, List> SuppressRule(string return result; } + public static string[] ProcessCustomRulePaths(string rulePath, SessionState sessionState, bool recurse = false) + { + //if directory is given, list all the psd1 files + List outPaths = new List(); + if (rulePath == null) + { + return null; + } + try + { + Collection pathInfo = sessionState.Path.GetResolvedPSPathFromPSPath(rulePath); + foreach (PathInfo pinfo in pathInfo) + { + string path = pinfo.Path; + if (Directory.Exists(path)) + { + path = path.TrimEnd('\\'); + if (recurse) + { + outPaths.AddRange(Directory.GetDirectories(pinfo.Path, "*", SearchOption.AllDirectories)); + } + } + outPaths.Add(path); + } + return outPaths.ToArray(); + } + catch (Exception ex) + { + // need to do this as the path validation takes place later in the hierarchy. + outPaths.Add(rulePath); + return outPaths.ToArray(); + } + } + + #endregion } + internal class TupleComparer : IComparer> { public int Compare(Tuple t1, Tuple t2) diff --git a/Engine/ScriptAnalyzer.cs b/Engine/ScriptAnalyzer.cs index 054db6758..b385fe4ae 100644 --- a/Engine/ScriptAnalyzer.cs +++ b/Engine/ScriptAnalyzer.cs @@ -108,7 +108,7 @@ internal void Initialize( { throw new ArgumentNullException("cmdlet"); } - + this.Initialize( cmdlet, cmdlet.SessionState.Path, @@ -188,7 +188,7 @@ private void Initialize( if (!String.IsNullOrWhiteSpace(profile)) { try - { + { profile = path.GetResolvedPSPathFromPSPath(profile).First().Path; } catch @@ -784,7 +784,7 @@ public Dictionary> CheckRuleExtension(string[] path, PathIn // We have to identify the childPath is really a directory or just a module name. // You can also consider following two commands. // Get-ScriptAnalyzerRule -RuleExtension "ContosoAnalyzerRules" - // Get-ScriptAnalyzerRule -RuleExtension "%USERPROFILE%\WindowsPowerShell\Modules\ContosoAnalyzerRules" + // Get-ScriptAnalyzerRule -RuleExtension "%USERPROFILE%\WindowsPowerShell\Modules\ContosoAnalyzerRules" if (Path.GetDirectoryName(childPath) == string.Empty) { resolvedPath = childPath; @@ -797,14 +797,14 @@ public Dictionary> CheckRuleExtension(string[] path, PathIn using (System.Management.Automation.PowerShell posh = System.Management.Automation.PowerShell.Create()) - { + { posh.AddCommand("Get-Module").AddParameter("Name", resolvedPath).AddParameter("ListAvailable"); PSModuleInfo moduleInfo = posh.Invoke().First(); // Adds original path, otherwise path.Except(validModPaths) will fail. // It's possible that user can provide something like this: // "..\..\..\ScriptAnalyzer.UnitTest\modules\CommunityAnalyzerRules\CommunityAnalyzerRules.psd1" - if (moduleInfo.ExportedFunctions.Count > 0) validModPaths.Add(childPath); + if (moduleInfo.ExportedFunctions.Count > 0) validModPaths.Add(resolvedPath); } } catch diff --git a/Tests/Engine/CustomizedRule.tests.ps1 b/Tests/Engine/CustomizedRule.tests.ps1 index cf87ed818..2ef337c88 100644 --- a/Tests/Engine/CustomizedRule.tests.ps1 +++ b/Tests/Engine/CustomizedRule.tests.ps1 @@ -51,18 +51,83 @@ Describe "Test importing correct customized rules" { } Context "Test Get-ScriptAnalyzer with customized rules" { - It "will show the customized rule" { + It "will show the custom rule" { $customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.RuleName -eq $measure} $customizedRulePath.Count | Should Be 1 } - + + It "will show the custom rule when given a rule folder path" { + $customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule | Where-Object {$_.RuleName -eq $measure} + $customizedRulePath.Count | Should Be 1 + } + + if (!$testingLibraryUsage) + { + It "will show the custom rule when given a rule folder path with trailing backslash" { + $customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\ | Where-Object {$_.RuleName -eq $measure} + $customizedRulePath.Count | Should Be 1 + } + + It "will show the custom rules when given a glob" { + $customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.RuleName -match $measure} + $customizedRulePath.Count | Should be 4 + } + + It "will show the custom rules when given recurse switch" { + $customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule | Where-Object {$_.RuleName -eq $measure} + $customizedRulePath.Count | Should be 3 + } + + it "will show the custom rules when given glob with recurse switch" { + $customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.RuleName -eq $measure} + $customizedRulePath.Count | Should be 5 + } + + it "will show the custom rules when given glob with recurse switch" { + $customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule* | Where-Object {$_.RuleName -eq $measure} + $customizedRulePath.Count | Should be 3 + } + } } Context "Test Invoke-ScriptAnalyzer with customized rules" { - It "will show the customized rule in the results" { + It "will show the custom rule in the results" { $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.Message -eq $message} $customizedRulePath.Count | Should Be 1 } + + It "will show the custom rule in the results when given a rule folder path" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should Be 1 + } + + if (!$testingLibraryUsage) + { + It "will show the custom rule in the results when given a rule folder path with trailing backslash" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\ | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should Be 1 + } + + It "will show the custom rules when given a glob" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should be 3 + } + + It "will show the custom rules when given recurse switch" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should be 3 + } + + it "will show the custom rules when given glob with recurse switch" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should be 4 + } + + it "will show the custom rules when given glob with recurse switch" { + $customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule* | Where-Object {$_.Message -eq $message} + $customizedRulePath.Count | Should be 3 + } + } } +} -} \ No newline at end of file diff --git a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 index 63895955c..32624e216 100644 --- a/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 +++ b/Tests/Engine/GetScriptAnalyzerRule.tests.ps1 @@ -19,12 +19,16 @@ Describe "Test available parameters" { Context "RuleExtension parameters" { It "has a RuleExtension parameter" { - $params.ContainsKey("CustomizedRulePath") | Should Be $true + $params.ContainsKey("CustomRulePath") | Should Be $true } It "accepts string array" { - $params["CustomizedRulePath"].ParameterType.FullName | Should Be "System.String[]" + $params["CustomRulePath"].ParameterType.FullName | Should Be "System.String" } + + It "takes CustomizedRulePath parameter as an alias of CustomRulePath paramter" { + $params.CustomRulePath.Aliases.Contains("CustomizedRulePath") | Should be $true + } } } diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index c85152b70..32db99599 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -30,19 +30,23 @@ Describe "Test available parameters" { $params.ContainsKey("ScriptDefinition") | Should Be $true } - It "accepts string" { + It "accepts string" { $params["ScriptDefinition"].ParameterType.FullName | Should Be "System.String" } } - Context "CustomizedRulePath parameters" { - It "has a CustomizedRulePath parameter" { - $params.ContainsKey("CustomizedRulePath") | Should Be $true + Context "CustomRulePath parameters" { + It "has a CustomRulePath parameter" { + $params.ContainsKey("CustomRulePath") | Should Be $true } - It "accepts string array" { - $params["CustomizedRulePath"].ParameterType.FullName | Should Be "System.String[]" + It "accepts a string" { + $params["CustomRulePath"].ParameterType.FullName | Should Be "System.String" } + + It "has a CustomizedRulePath alias"{ + $params.CustomRulePath.Aliases.Contains("CustomizedRulePath") | Should be $true + } } Context "IncludeRule parameters" { diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index 5e3c9694b..6b5664a5d 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -16,7 +16,11 @@ function Invoke-ScriptAnalyzer { [string] $ScriptDefinition, [Parameter(Mandatory = $false)] - [string[]] $CustomizedRulePath = $null, + [Alias("CustomizedRulePath")] + [string] $CustomRulePath = $null, + + [Parameter(Mandatory = $false)] + [switch] $RecurseCustomRulePath, [Parameter(Mandatory=$false)] [string[]] $ExcludeRule = $null, @@ -39,7 +43,7 @@ function Invoke-ScriptAnalyzer { $scriptAnalyzer.Initialize( $runspace, $testOutputWriter, - $CustomizedRulePath, + $CustomRulePath, $IncludeRule, $ExcludeRule, $Severity, diff --git a/Tests/Engine/samplerule/samplerule1.psm1 b/Tests/Engine/samplerule/samplerule1.psm1 new file mode 100644 index 000000000..cc94c6b1b --- /dev/null +++ b/Tests/Engine/samplerule/samplerule1.psm1 @@ -0,0 +1,47 @@ +#Requires -Version 3.0 + +<# +.SYNOPSIS + Uses #Requires -RunAsAdministrator instead of your own methods. +.DESCRIPTION + The #Requires statement prevents a script from running unless the Windows PowerShell version, modules, snap-ins, and module and snap-in version prerequisites are met. + From Windows PowerShell 4.0, the #Requires statement let script developers require that sessions be run with elevated user rights (run as Administrator). + Script developers does not need to write their own methods any more. + To fix a violation of this rule, please consider to use #Requires -RunAsAdministrator instead of your own methods. +.EXAMPLE + Measure-RequiresRunAsAdministrator -ScriptBlockAst $ScriptBlockAst +.INPUTS + [System.Management.Automation.Language.ScriptBlockAst] +.OUTPUTS + [OutputType([PSCustomObject[])] +.NOTES + None +#> +function Measure-RequiresRunAsAdministrator +{ + [CmdletBinding()] + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])] + Param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.Language.ScriptBlockAst] + $testAst + ) + + + $results = @() + + $result = [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]]@{"Message" = "this is help"; + "Extent" = $ast.Extent; + "RuleName" = $PSCmdlet.MyInvocation.InvocationName; + "Severity" = "Warning"} + + $results += $result + + + return $results + + +} +Export-ModuleMember -Function Measure* \ No newline at end of file diff --git a/Tests/Engine/samplerule/samplerule2/samplerule2.psm1 b/Tests/Engine/samplerule/samplerule2/samplerule2.psm1 new file mode 100644 index 000000000..cc94c6b1b --- /dev/null +++ b/Tests/Engine/samplerule/samplerule2/samplerule2.psm1 @@ -0,0 +1,47 @@ +#Requires -Version 3.0 + +<# +.SYNOPSIS + Uses #Requires -RunAsAdministrator instead of your own methods. +.DESCRIPTION + The #Requires statement prevents a script from running unless the Windows PowerShell version, modules, snap-ins, and module and snap-in version prerequisites are met. + From Windows PowerShell 4.0, the #Requires statement let script developers require that sessions be run with elevated user rights (run as Administrator). + Script developers does not need to write their own methods any more. + To fix a violation of this rule, please consider to use #Requires -RunAsAdministrator instead of your own methods. +.EXAMPLE + Measure-RequiresRunAsAdministrator -ScriptBlockAst $ScriptBlockAst +.INPUTS + [System.Management.Automation.Language.ScriptBlockAst] +.OUTPUTS + [OutputType([PSCustomObject[])] +.NOTES + None +#> +function Measure-RequiresRunAsAdministrator +{ + [CmdletBinding()] + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])] + Param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.Language.ScriptBlockAst] + $testAst + ) + + + $results = @() + + $result = [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]]@{"Message" = "this is help"; + "Extent" = $ast.Extent; + "RuleName" = $PSCmdlet.MyInvocation.InvocationName; + "Severity" = "Warning"} + + $results += $result + + + return $results + + +} +Export-ModuleMember -Function Measure* \ No newline at end of file diff --git a/Tests/Engine/samplerule/samplerule2/samplerule3/samplerule3.psm1 b/Tests/Engine/samplerule/samplerule2/samplerule3/samplerule3.psm1 new file mode 100644 index 000000000..cc94c6b1b --- /dev/null +++ b/Tests/Engine/samplerule/samplerule2/samplerule3/samplerule3.psm1 @@ -0,0 +1,47 @@ +#Requires -Version 3.0 + +<# +.SYNOPSIS + Uses #Requires -RunAsAdministrator instead of your own methods. +.DESCRIPTION + The #Requires statement prevents a script from running unless the Windows PowerShell version, modules, snap-ins, and module and snap-in version prerequisites are met. + From Windows PowerShell 4.0, the #Requires statement let script developers require that sessions be run with elevated user rights (run as Administrator). + Script developers does not need to write their own methods any more. + To fix a violation of this rule, please consider to use #Requires -RunAsAdministrator instead of your own methods. +.EXAMPLE + Measure-RequiresRunAsAdministrator -ScriptBlockAst $ScriptBlockAst +.INPUTS + [System.Management.Automation.Language.ScriptBlockAst] +.OUTPUTS + [OutputType([PSCustomObject[])] +.NOTES + None +#> +function Measure-RequiresRunAsAdministrator +{ + [CmdletBinding()] + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])] + Param + ( + [Parameter(Mandatory = $true)] + [ValidateNotNullOrEmpty()] + [System.Management.Automation.Language.ScriptBlockAst] + $testAst + ) + + + $results = @() + + $result = [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]]@{"Message" = "this is help"; + "Extent" = $ast.Extent; + "RuleName" = $PSCmdlet.MyInvocation.InvocationName; + "Severity" = "Warning"} + + $results += $result + + + return $results + + +} +Export-ModuleMember -Function Measure* \ No newline at end of file From 36bd5778541eb8fcaf001063a45f6fc245fb2d76 Mon Sep 17 00:00:00 2001 From: kborle Date: Fri, 20 Nov 2015 16:24:07 -0800 Subject: [PATCH 2/6] Fixes a bug in library usage test cmdlet --- Tests/Engine/LibraryUsage.tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index 6b5664a5d..f93e91f11 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -38,12 +38,12 @@ function Invoke-ScriptAnalyzer { [Parameter(Mandatory = $false)] [switch] $SuppressedOnly ) - + $customRulePathArr = @($CustomRulePath); $scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer" $scriptAnalyzer.Initialize( $runspace, $testOutputWriter, - $CustomRulePath, + $customRulePathArr, $IncludeRule, $ExcludeRule, $Severity, From 900de1118d2ab68ab39e59d4f89404ca77296f0e Mon Sep 17 00:00:00 2001 From: kborle Date: Fri, 20 Nov 2015 16:36:31 -0800 Subject: [PATCH 3/6] Modifies library usage test cmdlet. --- Tests/Engine/LibraryUsage.tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index f93e91f11..cf138b44b 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -38,7 +38,7 @@ function Invoke-ScriptAnalyzer { [Parameter(Mandatory = $false)] [switch] $SuppressedOnly ) - $customRulePathArr = @($CustomRulePath); + [string[]]$customRulePathArr = @($CustomRulePath); $scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer" $scriptAnalyzer.Initialize( $runspace, From 25ba9bd9e6ea9c5cf656e4e45df68a6c74fe68ec Mon Sep 17 00:00:00 2001 From: kborle Date: Fri, 20 Nov 2015 20:35:26 -0800 Subject: [PATCH 4/6] Fixes customRulePath parameter in library test --- Tests/Engine/LibraryUsage.tests.ps1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index cf138b44b..103c36d55 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -39,7 +39,12 @@ function Invoke-ScriptAnalyzer { [switch] $SuppressedOnly ) [string[]]$customRulePathArr = @($CustomRulePath); - $scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer" + if ($CustomRulePath -eq $null) + { + $customRulePathArr = $null; + } + + $scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer"; $scriptAnalyzer.Initialize( $runspace, $testOutputWriter, From 50ea0560aea2eb8b87a257199cb0c463476fa807 Mon Sep 17 00:00:00 2001 From: kborle Date: Fri, 20 Nov 2015 20:57:58 -0800 Subject: [PATCH 5/6] Adds profile parameter to the cmdlet in library tests --- Tests/Engine/LibraryUsage.tests.ps1 | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index 103c36d55..e7187337e 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -36,7 +36,10 @@ function Invoke-ScriptAnalyzer { [switch] $Recurse, [Parameter(Mandatory = $false)] - [switch] $SuppressedOnly + [switch] $SuppressedOnly, + + [Parameter(Mandatory = $false)] + [string] $Profile = $null ) [string[]]$customRulePathArr = @($CustomRulePath); if ($CustomRulePath -eq $null) @@ -52,7 +55,8 @@ function Invoke-ScriptAnalyzer { $IncludeRule, $ExcludeRule, $Severity, - $SuppressedOnly.IsPresent + $SuppressedOnly.IsPresent, + $Profile ); if ($PSCmdlet.ParameterSetName -eq "File") { From dbe3143dc0a0ee97d2877f499ba141117ec73291 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Sat, 21 Nov 2015 01:13:06 -0800 Subject: [PATCH 6/6] Creates a workaround the failing tests. We have set the CustomRulePath parameter in the cmdlet implementation in LibraryUsage.tests.ps1 to "string[]" type whereas in the c# implementation it is of "string" type. If we set the CustomRulePath parameter here to "string", then the library usage test fails when run as an administrator. We want to note that the library usage test doesn't fail when run as a non-admin user. Even if we create a "[string[]]" type object and pass it to Initialize method, the tests fail to run as an admin with the following error message. Assert failed on "Initialize" with "7" argument(s): "Test failed due to terminating error: The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018) --- Tests/Engine/InvokeScriptAnalyzer.tests.ps1 | 9 ++++++++- Tests/Engine/LibraryUsage.tests.ps1 | 15 ++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 index 32db99599..ab1d5dc7b 100644 --- a/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 +++ b/Tests/Engine/InvokeScriptAnalyzer.tests.ps1 @@ -41,7 +41,14 @@ Describe "Test available parameters" { } It "accepts a string" { - $params["CustomRulePath"].ParameterType.FullName | Should Be "System.String" + if ($testingLibraryUsage) + { + $params["CustomRulePath"].ParameterType.FullName | Should Be "System.String[]" + } + else + { + $params["CustomRulePath"].ParameterType.FullName | Should Be "System.String" + } } It "has a CustomizedRulePath alias"{ diff --git a/Tests/Engine/LibraryUsage.tests.ps1 b/Tests/Engine/LibraryUsage.tests.ps1 index e7187337e..49a1c6bdc 100644 --- a/Tests/Engine/LibraryUsage.tests.ps1 +++ b/Tests/Engine/LibraryUsage.tests.ps1 @@ -17,7 +17,7 @@ function Invoke-ScriptAnalyzer { [Parameter(Mandatory = $false)] [Alias("CustomizedRulePath")] - [string] $CustomRulePath = $null, + [string[]] $CustomRulePath = $null, [Parameter(Mandatory = $false)] [switch] $RecurseCustomRulePath, @@ -41,17 +41,18 @@ function Invoke-ScriptAnalyzer { [Parameter(Mandatory = $false)] [string] $Profile = $null ) - [string[]]$customRulePathArr = @($CustomRulePath); - if ($CustomRulePath -eq $null) - { - $customRulePathArr = $null; - } + # There is an inconsistency between this implementation and c# implementation of the cmdlet. + # The CustomRulePath parameter here is of "string[]" type whereas in the c# implementation it is of "string" type. + # If we set the CustomRulePath parameter here to "string[]", then the library usage test fails when run as an administrator. + # We want to note that the library usage test doesn't fail when run as a non-admin user. + # The following is the error statement when the test runs as an administrator. + # Assert failed on "Initialize" with "7" argument(s): "Test failed due to terminating error: The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018)" $scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer"; $scriptAnalyzer.Initialize( $runspace, $testOutputWriter, - $customRulePathArr, + $CustomRulePath, $IncludeRule, $ExcludeRule, $Severity,