private/tests-metadata/Get-ZtTestMetadata.ps1
function Get-ZtTestMetadata { <# .SYNOPSIS Reads the configured Test Metadata tracking information from commands. .DESCRIPTION Reads the configured Test Metadata tracking information from commands. This is added to the function definitions as a "ZtTest" attribute. .PARAMETER Test Select the command to process by Test ID. Will automatically look through the tests folder, pick the test and process. .PARAMETER Path Path to a script file to process. Will scan all top-level functions and return a result for each of them. .PARAMETER Command The command object to process. Must be a function definition. .PARAMETER IncludeMetadata Include PowerShell Metadata: - Path to the file containing the test - AST of the test code (the PowerShell Parser view of the test code) .EXAMPLE PS C:\> Get-ZtTestMetadata -Test 21770 Returns the metadata for the test with ID "21770" #> [CmdletBinding()] param ( [string[]] $Test, [PSFFile] $Path, [System.Management.Automation.FunctionInfo[]] $Command, [switch] $IncludeMetadata ) begin { #region Utility Functions function Get-TestFunctionAst { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $TestRoot, [Parameter(Mandatory = $true)] [string] $Test ) $filePath = Join-Path -Path $TestRoot -ChildPath "Test-Assessment.$Test.ps1" if (-not (Test-Path -Path $filePath)) { Write-Error "Test not found: $Test" return } $testItem = Get-PathFunctionAst -Path $filePath | Where-Object Name -EQ "Test-Assessment-$Test" if (-not $testItem) { Write-Error "Test File found, but does not contain a command 'Test-Assessment-$Test'!" return } $testItem } function Get-PathFunctionAst { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $Path ) $ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$null, [ref]$null) $functionDefinitions = [System.Collections.Generic.List[object]]::new() foreach ($statement in $ast.BeginBlock.Statements) { if ($statement -is [System.Management.Automation.Language.FunctionDefinitionAst]) { $functionDefinitions.Add($statement) } } foreach ($statement in $ast.ProcessBlock.Statements) { if ($statement -is [System.Management.Automation.Language.FunctionDefinitionAst]) { $functionDefinitions.Add($statement) } } foreach ($statement in $ast.EndBlock.Statements) { if ($statement -is [System.Management.Automation.Language.FunctionDefinitionAst]) { $functionDefinitions.Add($statement) } } foreach ($functionDefinition in $functionDefinitions) { [PSCustomObject]@{ Name = $functionDefinition.Name Ast = $functionDefinition File = $functionDefinition.Extent.File -replace '^.+(\\|/)' Path = $functionDefinition.Extent.File } } } function Get-FunctionAst { [CmdletBinding()] param ( [System.Management.Automation.FunctionInfo] $Command ) [PSCustomObject]@{ Name = $Command.Name Ast = $Command.ScriptBlock.Ast File = $Command.ScriptBlock.Ast.Extent.File -replace '^.+(\\|/)' Path = $Command.ScriptBlock.Ast.Extent.File } } #endregion Utility Functions # Case: Loaded through the module if ($script:ModuleRoot) { $testRoot = "$script:ModuleRoot\tests" } # Case: Called Directly from the build tools else { $testRoot = "$PSScriptRoot\..\..\tests" } } process { $commandAsts = [System.Collections.Generic.List[object]]::new() $astResults = foreach ($testID in $Test) { Get-TestFunctionAst -TestRoot $testRoot -Test $testID } if ($astResults) { $commandAsts.AddRange(@($astResults)) } $astResults = foreach ($filePath in $Path) { Get-PathFunctionAst -Path $filePath } if ($astResults) { $commandAsts.AddRange(@($astResults)) } $astResults = foreach ($functionDefinition in $Command) { Get-FunctionAst -Command $functionDefinition } if ($astResults) { $commandAsts.AddRange(@($astResults)) } foreach ($commandItem in $commandAsts) { $result = [PSCustomObject]@{ PSTypeName = 'ZeroTrustAssessment.Test' Command = $commandItem.Name TestId = $commandItem.Ast.Name -replace '^Test-Assessment-' Category = $null ImplementationCost = $null Pillar = $null RiskLevel = $null SfiPillar = $null TenantType = $null Title = $null UserImpact = $null } if ($IncludeMetadata) { $extra = @{ Path = $commandItem.Path Ast = $commandItem.Ast } if ($extra.Path -and (Test-Path -Path $extra.Path)) { $extra.Path = (Get-Item -LiteralPath $extra.Path).FullName } [PSFramework.Object.ObjectHost]::AddNoteProperty($result, $extra) } $testAttribute = $commandItem.Ast.Body.ParamBlock.Attributes.Where{ $_.TypeName.FullName -eq 'ZtTest' } if ($testAttribute) { foreach ($argument in $testAttribute.NamedArguments) { if ($result.PSObject.Properties.Name -notcontains $argument.ArgumentName) { continue } $result.$($argument.ArgumentName) = $argument.Argument.SafeGetValue() } } $result } } } |