private/tests/Invoke-ZtTestParallel.ps1

function Invoke-ZtTestParallel {
    <#
    .SYNOPSIS
        Execute individual tests and collect execution statistics.
 
    .DESCRIPTION
        Execute individual tests and collect execution statistics.
        This command is expected to be run from background runspaces launched by Start-ZtTestExecution.
 
        Use Get-ZtTestStatistics to retrieve the results of these executions.
 
    .PARAMETER Test
        The test object to process.
        Expects an object as returned by Get-ZtTest.
 
    .PARAMETER Database
        The Database used for accessing cached tenant data.
 
    .PARAMETER LogsPath
        Path to the logs folder where per-test log files are written.
        If not specified, no log files are written.
 
    .PARAMETER PreviousMessages
        The messages previously sent from this runspace.
        Used to include only messages written afterwards in the test statistics.
 
    .EXAMPLE
        PS C:\> Invoke-ZtTestParallel -Test $_ -Database $global:database -LogsPath $logsPath
 
        Executes the current test with the globally cached database connection and writes a log file.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [PSTypeName('ZeroTrustAssessment.Test')]
        $Test,

        [DuckDB.NET.Data.DuckDBConnection]
        $Database,

        [string]
        $LogsPath,

        $PreviousMessages
    )
    begin {
        $result = Get-ZtTestResult -Test $Test
    }
    process {
        Write-PSFMessage -Message "Processing test '{0}'" -StringValues $Test.TestID -Target $Test -Tag start

        # Update progress dashboard: map this runspace to this test and mark as starting
        $runspaceId = [runspace]::DefaultRunspace.InstanceId.ToString()
        $script:__ZtSession.ProgressState.Value["rs_$runspaceId"] = $Test.TestID
        Update-ZtProgressState -WorkerId $Test.TestID -WorkerName $result.DisplayName -WorkerStatus 'Running' -WorkerDetail 'Starting test...'

        # Check if the function exists and what parameters it has
        $command = Get-Command $Test.Command -ErrorAction SilentlyContinue
        if (-not $command) {
            Write-PSFMessage -Level Warning -Message "Test command for test '{0}' not found" -StringValues $Test.TestID -Target $Test
            throw "Test command for test '$($Test.TestID)' not found"
        }

        $dbParam = @{}
        if (($null -ne $command) -and $command.Parameters.ContainsKey("Database") -and $Database) {
            $dbParam.Database = $Database
        }

        # Write stub log file and progress entry so hanging tests are visible
        if ($LogsPath) {
            Write-ZtTestProgress -TestID $Test.TestID -LogsPath $LogsPath -Action Started
            try {
                $stubDir = Join-Path $LogsPath '2-Tests'
                [void][System.IO.Directory]::CreateDirectory($stubDir)
                $stubPath = Join-Path $stubDir "$($Test.TestID).md"
                [System.IO.File]::WriteAllText($stubPath, "# Test: $($Test.TestID) - Started at $((Get-Date).ToString('yyyy-MM-dd HH:mm:ss.fff'))$([System.Environment]::NewLine)")
            }
            catch {
                Write-PSFMessage -Level Warning -Message "Failed to write stub test log for test '{0}': {1}" -StringValues $Test.TestID, $_ -Tag log
            }
        }

        try {
            # Set Current Test for "Add-ZtTestResultDetail to pick up"
            $script:__ztCurrentTest = $Test

            # Only start on first attempt - retries count as extra
            if (-not $result.Start) {
                $result.Start = Get-Date
            }
            else {
                $result.Attempts++
            }

            $result.Output = & $command @dbParam -ErrorAction Stop
        }
        catch {
            throw
        }
        finally {
            # Reset marker in an assured way, to prevent confusion about the current test being executed
            $script:__ztCurrentTest = $null
        }

        $result.End = Get-Date
        $result.Duration = $result.End - $result.Start

        Write-PSFMessage -Message "Processing test '{0}' - Concluded" -StringValues $Test.TestID -Target $Test -Tag end
    }

    end {
        Write-ZtTestFinish -Result $result -PreviousMessages $previousMessages -Test $Test -LogsPath $LogsPath -PassThru
    }
}