[CmdletBinding()] param( [string]$DigestPath = (Join-Path (Split-Path -Parent $PSScriptRoot) 'target\release-fast\mhash.exe'), [string]$OutputRoot = (Join-Path (Split-Path -Parent $PSScriptRoot) 'target\mhash-benchmark\smoke'), [switch]$SkipBuild ) $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest function Assert-Smoke { param( [Parameter(Mandatory = $true)] [bool]$Condition, [Parameter(Mandatory = $true)] [string]$Message ) if (-not $Condition) { throw "Smoke assertion failed: $Message" } } function Get-SingleLatestFile { param( [Parameter(Mandatory = $true)] [string]$Root, [Parameter(Mandatory = $true)] [string]$Filter ) $file = Get-ChildItem -LiteralPath $Root -Filter $Filter -File | Sort-Object LastWriteTimeUtc -Descending | Select-Object -First 1 Assert-Smoke -Condition ($null -ne $file) -Message "Expected $Filter under $Root." return $file } function Read-JsonFile { param( [Parameter(Mandatory = $true)] [string]$Path ) return Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json } $harness = Join-Path $PSScriptRoot 'benchmark-mhash.ps1' $stamp = Get-Date -Format 'yyyyMMdd-HHmmss' $smokeRoot = Join-Path $OutputRoot $stamp $runRoot = Join-Path $smokeRoot 'results' $dataRoot = Join-Path $smokeRoot 'data' $benchmarkArgs = @{ DataRoot = $dataRoot OutputRoot = $runRoot Sizes = @('1KiB') Algorithms = @('sha256') Repeat = 1 Warmup = 0 DigestPath = $DigestPath NoExternal = $true DigestFormats = @('sum', 'jsonl') } if ($SkipBuild) { $benchmarkArgs.SkipBuild = $true } & $harness @benchmarkArgs $rawPath = Get-SingleLatestFile -Root $runRoot -Filter '*.raw.json' $summaryPath = Get-SingleLatestFile -Root $runRoot -Filter '*.summary.json' $recordsJsonlPath = Get-SingleLatestFile -Root $runRoot -Filter '*.records.jsonl' $summaryJsonlPath = Get-SingleLatestFile -Root $runRoot -Filter '*.summary.jsonl' $artifactsPath = Get-SingleLatestFile -Root $runRoot -Filter '*.artifacts.json' $raw = Read-JsonFile -Path $rawPath.FullName $summary = @(Read-JsonFile -Path $summaryPath.FullName) $artifacts = @(Read-JsonFile -Path $artifactsPath.FullName) $records = @($raw.records) $recordsJsonlLines = @(Get-Content -LiteralPath $recordsJsonlPath.FullName) $summaryJsonlLines = @(Get-Content -LiteralPath $summaryJsonlPath.FullName) Assert-Smoke -Condition ($raw.environment.mhash_formats.Count -eq 2) -Message 'Expected both sum and jsonl mhash formats in environment metadata.' Assert-Smoke -Condition ($raw.environment.size_only -eq $false) -Message 'Expected normal benchmark mode in raw environment metadata.' Assert-Smoke -Condition ($artifacts.Count -ge 1) -Message 'Expected at least one tool artifact record.' Assert-Smoke -Condition ($records.Count -eq 4) -Message "Expected 4 measured records, got $($records.Count)." Assert-Smoke -Condition ($summary.Count -eq 4) -Message "Expected 4 summary records, got $($summary.Count)." Assert-Smoke -Condition ($recordsJsonlLines.Count -eq $records.Count) -Message 'Records JSONL line count should match raw record count.' Assert-Smoke -Condition ($summaryJsonlLines.Count -eq $summary.Count) -Message 'Summary JSONL line count should match summary count.' foreach ($record in $records) { Assert-Smoke -Condition ($record.binary_size_bytes -gt 0) -Message 'Each measured record should include binary_size_bytes.' Assert-Smoke -Condition (-not [string]::IsNullOrWhiteSpace($record.output_format)) -Message 'Each measured record should include output_format.' Assert-Smoke -Condition ($record.peak_working_set_bytes -gt 0) -Message 'Each measured record should include peak_working_set_bytes.' } foreach ($row in $summary) { Assert-Smoke -Condition ($row.binary_size_bytes -gt 0) -Message 'Each summary row should include binary_size_bytes.' Assert-Smoke -Condition (-not [string]::IsNullOrWhiteSpace($row.output_format)) -Message 'Each summary row should include output_format.' } $sizeOnlyRoot = Join-Path $smokeRoot 'size-only' $sizeOnlyArgs = @{ DataRoot = (Join-Path $smokeRoot 'size-only-data') OutputRoot = $sizeOnlyRoot Sizes = @('1KiB') Algorithms = @('sha256', 'blake3-256', 'blake2sp', 'xxh3-64', 'xxh3-128', 'crc32', 'crc64-xz', 'k12-256', 'parallelhash256-528') Repeat = 1 Warmup = 0 DigestPath = $DigestPath SkipBuild = $true NoExternal = $true SizeOnly = $true } & $harness @sizeOnlyArgs $sizeOnlyRawPath = Get-SingleLatestFile -Root $sizeOnlyRoot -Filter '*.raw.json' $sizeOnlySummaryPath = Get-SingleLatestFile -Root $sizeOnlyRoot -Filter '*.summary.json' $sizeOnlyHyperfinePath = Get-SingleLatestFile -Root $sizeOnlyRoot -Filter '*.hyperfine.json' $sizeOnlyArtifactsPath = Get-SingleLatestFile -Root $sizeOnlyRoot -Filter '*.artifacts.json' $sizeOnlyRaw = Read-JsonFile -Path $sizeOnlyRawPath.FullName $sizeOnlySummary = @(Read-JsonFile -Path $sizeOnlySummaryPath.FullName) $sizeOnlyHyperfine = @(Read-JsonFile -Path $sizeOnlyHyperfinePath.FullName) $sizeOnlyArtifacts = @(Read-JsonFile -Path $sizeOnlyArtifactsPath.FullName) Assert-Smoke -Condition ($sizeOnlyRaw.environment.size_only -eq $true) -Message 'Expected size-only mode in raw environment metadata.' Assert-Smoke -Condition ($sizeOnlyRaw.environment.algorithms -contains 'blake3-256') -Message 'Size-only smoke should accept extended mhash benchmark algorithms.' Assert-Smoke -Condition ($sizeOnlyRaw.environment.algorithms -contains 'parallelhash256-528') -Message 'Size-only smoke should accept ParallelHash mhash benchmark algorithms.' Assert-Smoke -Condition (@($sizeOnlyRaw.records).Count -eq 0) -Message 'Size-only mode should not emit measured records.' Assert-Smoke -Condition ($sizeOnlySummary.Count -eq 0) -Message 'Size-only summary JSON should be an empty array.' Assert-Smoke -Condition ($sizeOnlyHyperfine.Count -eq 0) -Message 'Size-only hyperfine JSON should be an empty array.' Assert-Smoke -Condition ($sizeOnlyArtifacts.Count -ge 1) -Message 'Size-only mode should still emit artifact telemetry.' Write-Host "Smoke benchmark raw: $($rawPath.FullName)" Write-Host "Smoke size-only raw: $($sizeOnlyRawPath.FullName)" Write-Host "Smoke assertions passed: records=$($records.Count), summary=$($summary.Count), artifacts=$($artifacts.Count)"