Skip to content

test(rules): the 7-only cmdlet, parameter and value tables are checked against both hosts - #12

Merged
fadwen merged 1 commit into
fix/harness-password-task-accountfrom
test/ps7-tables-against-hosts
Oct 6, 2026
Merged

fadwen merged 1 commit into
fix/harness-password-task-accountfrom
test/ps7-tables-against-hosts

Conversation

@fadwen

@fadwen fadwen commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Summary

IslPowerShell7Syntax reports cmdlets, parameters and parameter values that PowerShell 7 has and Windows PowerShell 5.1 lacks, from tables kept by hand inside the rule. The 0.26.0 audit found two parameters there that exist on neither host, and a value the rule never matched. This moves the tables into one private function and adds a unit test that holds every entry against both hosts as child processes, so a wrong entry fails the suite instead of waiting for the next audit.

The test found three more wrong entries on its first run, which this pull request also removes.

Changes

  • Private/Get-IslCoreOnlyFeature.ps1 (new). The three tables, Commands, Parameters and Values, in one place; the rule reads them from here. No finding changes its message, severity or evidence; docs/Rules.md is unchanged.
  • Three entries removed. Switch-Process: PowerShell 7 has it on Linux and macOS only, so a script calling it fails on both Windows hosts. Invoke-WebRequest -StatusCodeVariable: exists on neither host; only Invoke-RestMethod has it. Get-ChildItem -FollowSymlink: Windows PowerShell has had it since 5.0.
  • Tests/Unit/Private/Get-IslCoreOnlyFeature.Tests.ps1 (new). Sends the tables to powershell.exe and pwsh.exe as child processes, which answer for every command whether it exists, for every parameter whether its command has it, and for every value whether the parameter's ValidateSet takes it. Each entry must be absent from 5.1 and present in 7; a value must be refused by 5.1 and taken by 7. ForEach-Object -Parallel, which the rule handles on its own, is checked the same way. The hosts are asked as child processes, so the test gives the same answer whichever host runs it; it is skipped where either executable is missing. CI's Windows runners have both.

Verification

  • Unit and integration suites: 932 pass on PowerShell 7.6.6 (8 skipped: elevation, lab credential); 882 pass on Windows PowerShell 5.1 for the unit suites and two integration files (33 skipped). PSScriptAnalyzer (Error and Warning) is clean; no line over 115 characters; the help Markdown validates; the rule reference regenerates unchanged.
  • The new test, before the three entries were removed, reported exactly those three: "Switch-Process is missing from 7", "Invoke-WebRequest -StatusCodeVariable is missing from 7", "Get-ChildItem -FollowSymlink exists in 5.1".

Notes

@fadwen fadwen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes on the lines whose reason the diff does not show.

# Switch-Process is not here: PowerShell 7 has it on Linux and macOS only, so a script that
# calls it fails on both Windows hosts. Get-ChildItem -FollowSymlink is not here either:
# Windows PowerShell 5.0 already had it. Both were listed until the test below ran
Commands = [string[]]@(

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typed, here and for the Out-File value below, so a table cut down to one entry still serializes as an array when the test sends it to the hosts as JSON; a lone string would arrive as a scalar and the probe would iterate its characters.

Commands = @($script:Table.Commands)
Parameters = @(foreach ($command in $script:Table.Parameters.Keys) {
@{ Command = $command; Parameters = @($script:Table.Parameters[$command]) }
}) + @(@{ Command = 'ForEach-Object'; Parameters = @('Parallel') })

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ForEach-Object -Parallel is not in the table because the rule handles it on its own path, with the REM-PS7-PARALLEL evidence. Added to the probe here so it is held against the hosts all the same.

})
}
$json = $flat | ConvertTo-Json -Depth 5 -Compress
$command = "& { $($probe.ToString()) } '$($json.Replace("'", "''"))'"

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table travels as a single-quoted literal argument inside the encoded command, so no JSON quoting crosses the command line, and -EncodedCommand carries the same bytes to both hosts.

function script:Get-HostAnswer {
param([string]$Exe, [string]$Command)
$raw = & $Exe -NoProfile -NonInteractive -EncodedCommand $Command 2>&1
($raw | Where-Object { "$_".StartsWith('{') } | Select-Object -Last 1) | ConvertFrom-Json

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either host can print lines of its own before the answer: module import noise, or a stderr record merged in by 2>&1. The answer is the last line that starts with a brace.


It 'every listed parameter is missing from the 5.1 command and present on the 7 one' {
$keys = @($script:Core.Parameters.PSObject.Properties.Name)
$keys.Count | Should-BeGreaterThan 30

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A guard that the probe answered at all. Without it a probe that failed to read the table would return no keys, and the three assertions would pass on an empty set.

@fadwen
fadwen added this pull request to stack #15 October 6, 2026 06:46
…d against both hosts

The tables IslPowerShell7Syntax reports from were kept by hand inside the rule; the 0.26.0 audit found entries that exist on neither host. They live in Get-IslCoreOnlyFeature now, and a unit test sends them to powershell.exe and pwsh.exe as child processes: every entry must be absent from 5.1 and present in 7. On its first run it found three more wrong entries, removed here: Switch-Process (Linux and macOS only), Invoke-WebRequest -StatusCodeVariable (neither host) and Get-ChildItem -FollowSymlink (in 5.1 since 5.0).
@fadwen
fadwen force-pushed the test/ps7-tables-against-hosts branch from c745a01 to 54b42a1 Compare October 6, 2026 06:52
@fadwen
fadwen merged commit f20cfe5 into main Oct 6, 2026
4 checks passed
@fadwen
fadwen deleted the test/ps7-tables-against-hosts branch October 6, 2026 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant