Skip to content

Commit 8d33bf4

Browse files
committed
test: ✨ Add test for custom rule suppression with RuleSuppressionID
* Implemented a test case to validate the functionality of custom rules with targeted suppression. * The test recreates the scenario from GitHub issue #1686, ensuring that `RuleSuppressionID` works correctly with named arguments. * Verified that violations are suppressed as expected based on the defined rules.
1 parent b80a609 commit 8d33bf4

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

Tests/Engine/RuleSuppression.tests.ps1

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,111 @@ function SuppressPasswordParam()
296296
# All violations should be suppressed since there's no RuleSuppressionID filtering
297297
$diagnostics | Should -HaveCount 0
298298
}
299+
300+
It "Should work with custom rule from issue #1686 comment" {
301+
# This test recreates the exact scenario from GitHub issue 1686 comment
302+
# with a custom rule that populates RuleSuppressionID for targeted suppression
303+
304+
# Custom rule module that creates violations with specific RuleSuppressionIDs
305+
$customRuleScript = @'
306+
function Measure-AvoidFooBarCommand {
307+
[CmdletBinding()]
308+
[OutputType([Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
309+
param(
310+
[Parameter(Mandatory)]
311+
[ValidateNotNullOrEmpty()]
312+
[System.Management.Automation.Language.ScriptBlockAst]
313+
$ScriptBlockAst
314+
)
315+
316+
$results = @()
317+
318+
# Find all command expressions
319+
$commandAsts = $ScriptBlockAst.FindAll({
320+
param($node)
321+
$node -is [System.Management.Automation.Language.CommandAst]
322+
}, $true)
323+
324+
foreach ($commandAst in $commandAsts) {
325+
$commandName = $commandAst.GetCommandName()
326+
if ($commandName -match '^(Get-FooBar|Set-FooBar)$') {
327+
# Create a diagnostic with the command name as RuleSuppressionID
328+
$result = [Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord]::new(
329+
"Avoid using $commandName command",
330+
$commandAst.Extent,
331+
'Measure-AvoidFooBarCommand',
332+
'Warning',
333+
$null,
334+
$commandName # This becomes the RuleSuppressionID
335+
)
336+
$results += $result
337+
}
338+
}
339+
340+
return $results
341+
}
342+
343+
Export-ModuleMember -Function Measure-AvoidFooBarCommand
344+
'@
345+
346+
# Script that uses the custom rule with targeted suppression
347+
$scriptWithCustomRuleSuppression = @'
348+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('Measure-AvoidFooBarCommand', RuleSuppressionId = 'Get-FooBar', Scope = 'Function', Target = 'Allow-GetFooBar')]
349+
param()
350+
351+
function Test-BadCommands {
352+
Get-FooBar # Line 6 - Should NOT be suppressed (wrong function)
353+
Set-FooBar # Line 7 - Should NOT be suppressed (different RuleSuppressionID)
354+
}
355+
356+
function Allow-GetFooBar {
357+
Get-FooBar # Line 11 - Should be suppressed (matches RuleSuppressionId and Target)
358+
Set-FooBar # Line 12 - Should NOT be suppressed (different RuleSuppressionID)
359+
}
360+
'@
361+
362+
# Save custom rule to temporary file
363+
$customRuleFile = [System.IO.Path]::GetTempFileName()
364+
$customRuleModuleFile = [System.IO.Path]::ChangeExtension($customRuleFile, '.psm1')
365+
Set-Content -Path $customRuleModuleFile -Value $customRuleScript
366+
367+
try
368+
{
369+
# Check suppressed violations - this is the key test for our fix
370+
$suppressions = Invoke-ScriptAnalyzer `
371+
-ScriptDefinition $scriptWithCustomRuleSuppression `
372+
-CustomRulePath $customRuleModuleFile `
373+
-SuppressedOnly `
374+
-ErrorAction SilentlyContinue
375+
376+
# The core functionality: RuleSuppressionID with named arguments should work for custom rules
377+
# We should have at least one suppressed Get-FooBar violation
378+
$suppressions | Should -Not -BeNullOrEmpty -Because "RuleSuppressionID named arguments should work for custom rules"
379+
380+
$getFooBarSuppressions = $suppressions | Where-Object { $_.RuleSuppressionID -eq 'Get-FooBar' }
381+
$getFooBarSuppressions | Should -Not -BeNullOrEmpty -Because "Get-FooBar should be suppressed based on RuleSuppressionID"
382+
383+
# Verify the suppression occurred in the right function (Allow-GetFooBar)
384+
$getFooBarSuppressions | Should -Not -BeNullOrEmpty
385+
$getFooBarSuppressions[0].RuleName | Should -BeExactly 'Measure-AvoidFooBarCommand'
386+
387+
# Get unsuppressed violations to verify selective suppression
388+
$diagnostics = Invoke-ScriptAnalyzer `
389+
-ScriptDefinition $scriptWithCustomRuleSuppression `
390+
-CustomRulePath $customRuleModuleFile `
391+
-ErrorAction SilentlyContinue
392+
393+
# Should still have violations for Set-FooBar (different RuleSuppressionID) and Get-FooBar in wrong function
394+
$setFooBarViolations = $diagnostics | Where-Object { $_.RuleSuppressionID -eq 'Set-FooBar' }
395+
$setFooBarViolations | Should -Not -BeNullOrEmpty -Because "Set-FooBar should not be suppressed (different RuleSuppressionID)"
396+
397+
}
398+
finally
399+
{
400+
Remove-Item -Path $customRuleModuleFile -ErrorAction SilentlyContinue
401+
Remove-Item -Path $customRuleFile -ErrorAction SilentlyContinue
402+
}
403+
}
299404
}
300405

301406
Context "Rule suppression within DSC Configuration definition" {

0 commit comments

Comments
 (0)