diff --git a/.github/workflows/test-iseberg.yml b/.github/workflows/test-iseberg.yml index dc33dde..79c8d10 100644 --- a/.github/workflows/test-iseberg.yml +++ b/.github/workflows/test-iseberg.yml @@ -15,6 +15,7 @@ on: - "NuGet.Config" - "global.json" - "scripts/Install-IsebergTestPowerShell.ps1" + - "scripts/Test-IsebergCore.ps1" pull_request: paths: - ".github/workflows/test-iseberg.yml" @@ -27,6 +28,7 @@ on: - "NuGet.Config" - "global.json" - "scripts/Install-IsebergTestPowerShell.ps1" + - "scripts/Test-IsebergCore.ps1" schedule: - cron: "0 6 * * 1" workflow_dispatch: @@ -70,24 +72,10 @@ jobs: shell: pwsh run: ./scripts/Install-IsebergTestPowerShell.ps1 - - name: Test engine, workbench, and settings - timeout-minutes: 120 + - name: Test Iseberg core + timeout-minutes: 20 shell: pwsh - run: | - $ErrorActionPreference = 'Stop' - $PSNativeCommandUseErrorActionPreference = $true - foreach ($project in @( - 'Devolutions.Terminal.App.Tests', - 'Devolutions.Terminal.UI.Tests', - 'Devolutions.Terminal.Settings.Tests', - 'Devolutions.Terminal.Settings.Editor.Tests' - )) { - dotnet test "tests/$project/$project.csproj" -c Release -m:1 ` - -p:EnablePowerShellIse=true ` - --logger "console;verbosity=normal" --logger trx ` - --results-directory "artifacts/test-results/$project" ` - --blame-hang --blame-hang-timeout 5min --blame-hang-dump-type none - } + run: ./scripts/Test-IsebergCore.ps1 - name: Upload test diagnostics if: always() diff --git a/docs/iseberg.md b/docs/iseberg.md index ae5d2c7..d0a3cfd 100644 --- a/docs/iseberg.md +++ b/docs/iseberg.md @@ -268,15 +268,31 @@ excluded when the feature is off. CI publishes the feature-enabled NativeAOT desktop and verifies its package and module signatures. The separate `test-iseberg.yml` workflow tests Iseberg on Windows, Linux, and macOS using the pinned PowerShell 7.6.6 runtime. It runs -the App, UI, Settings, and Settings.Editor test projects, not the entire -solution, and checks terminal-only Windows x64/ARM64 NativeAOT publishes. +`scripts/Test-IsebergCore.ps1` to select a fast core from the App, UI, Settings, +and Settings.Editor projects, and checks terminal-only Windows x64/ARM64 +NativeAOT publishes. The core retains 220 of the 1,104 Iseberg cases in the +original Windows run (80% fewer): inexpensive editor, installation, handshake, +protocol, and child-process checks plus representative native-console execution, +input, cancellation, recovery, profile, and settings-editor workflows. Exhaustive +hosted workbench, theme, and native-input permutations are outside the CI core; +the terminal-only workflow already covers unrelated terminal tests. Source/dependency changes, a weekly schedule, and -manual dispatch trigger it; the extended suite does not gate release publication. +manual dispatch trigger it; the core suite does not gate release publication. Iseberg CI runs test projects sequentially (`-m:1`) to avoid concurrent test-host startup starving short broker deadlines. It retains TRX results and per-test -hang diagnostics and a 120-minute test-step budget for the slower hosted Windows +hang diagnostics and a 20-minute test-step budget for the slower hosted Windows runner. A failed App test project stops the step before starting the UI suite. +Run the same core locally after installing the test runtime: + +```powershell +. ./scripts/Install-IsebergTestPowerShell.ps1 +./scripts/Test-IsebergCore.ps1 +``` + +The full regression suite remains available through the unfiltered solution test +command above; no regression tests have been deleted. + Native libraries/helpers and legal notices remain loose for package signing and license checks. Ship only `Devolutions.Iseberg.PowerShell.dll` as loose content directly beside `dt.exe` and the desktop executable; it is not loaded into DT. Shared contract sources diff --git a/scripts/Test-IsebergCore.ps1 b/scripts/Test-IsebergCore.ps1 new file mode 100644 index 0000000..62c9f6b --- /dev/null +++ b/scripts/Test-IsebergCore.ps1 @@ -0,0 +1,81 @@ +#Requires -Version 7.4 +[CmdletBinding()] +param() + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' +$PSNativeCommandUseErrorActionPreference = $true + +# Keep inexpensive editor/transport coverage and representative hosted workflows, +# not the exhaustive workbench, theme, and native-input permutations. +$tests = [ordered]@{ + 'Devolutions.Terminal.App.Tests' = @( + 'PortableIseInstallationTests.' + 'PortableIseHandshakeTests.' + 'PortableIseProtocolTests.' + 'PortableIseProcessTests.' + 'PortableIseCoreTests.PersistenceLeaseContentionPreservesFirstOwnerAndLockBytes' + 'PortableIseCoreTests.ReleasedRecoveryPreservesDirtyDraftFields' + 'PortableIseCoreTests.LiveRecoveryRecordsOwnProcessButIsNotEligibleUntilReleased' + 'PortableIseCoreTests.DirtySavedRecoveryRecordsAbsolutePathAndCurrentEncoding' + 'PortableIseCoreTests.CleanSaveRemovesOnlyOwnSnapshot' + 'PowerShellIseWorkspaceCatalogTests.ConcurrentProfileRecordsPublishOneOwnerAndNeverRebind' + 'PowerShellIseWorkspaceCatalogTests.SameProfileReleasedWorkspaceIsFoundWithoutConsumingOrRewritingData' + ) + 'Devolutions.Terminal.UI.Tests' = @( + 'PortableIseEditorTests.' + 'IsebergTerminalBridgeTests.ScriptAndNativeConsoleSharePersistentRunspace' + 'IsebergTerminalBridgeTests.NativeReadHostAcceptsResponseAndKeepsRunspaceUsable' + 'IsebergTerminalBridgeTests.NativeCtrlCStopsRunningCommandAndRestoresInput' + 'IsebergTerminalBridgeTests.MultilinePasteWaitsForExplicitEnter' + 'IsebergTerminalBridgeTests.ResizeUpdatesRawUiColumnsWithoutReplacingEngine' + 'IsebergNativeContinuationTests.ParenthesizedContinuationCompletedAfterFirstEnterExecutesExactlyOnce' + 'IsebergNativeContinuationTests.CompleteInvalidInputPublishesOneParseErrorWithoutEnteringContinuation' + 'PowerShellIseTabTests.DirtyCloseCancellationPreservesDocumentAndEngine' + 'MainWindowPowerShellIseTests.SavedIseProfileLaunchesAndCapturesRealWorkbenchTab' + 'PortableIseWorkbenchTests.ExplicitRecoverySavesExactDocumentsSelectionCaretAndReleasedOwnership' + 'PortableIseWorkbenchTests.RecoverRoutesSameNamedDocumentsToSavedSessionsAndRestoresActiveSession' + ) + 'Devolutions.Terminal.Settings.Tests' = @( + 'PowerShellIseProfileTests.IseDiscriminatorAndExplicitOptInResolve' + 'PowerShellIseProfileTests.AddedIseProfileRoundTripsKindOptionsAndIdentity' + 'PowerShellIseProfileTests.UnknownProfileTypeIsUnsupportedWithError' + 'PowerShellIseProfileTests.NewIseProfileUsesIsebergNameAndDistinctIdentity' + 'PowerShellIseProfileTests.TerminalProfilesAndOverridesRemainTerminal' + 'PowerShellIseProfileTests.IseThemeDefaultsToClassicWithoutAddingThemeToLegacyTerminal' + 'PowerShellIseProfileTests.UnknownIseThemeIsPreservedWithoutDefaultOrTerminalFallback' + ) + 'Devolutions.Terminal.Settings.Editor.Tests' = @( + 'IseProfileHarmonizationTests.' + ) +} + +$elapsed = [Diagnostics.Stopwatch]::StartNew() +Push-Location (Join-Path $PSScriptRoot '..') +try { + foreach ($selection in $tests.GetEnumerator()) { + $project = $selection.Key + $filter = ($selection.Value | ForEach-Object { "FullyQualifiedName~$project.$_" }) -join '|' + $projectPath = Join-Path 'tests' (Join-Path $project "$project.csproj") + $resultsDirectory = Join-Path (Join-Path 'artifacts' 'test-results') $project + $resultsPath = Join-Path $resultsDirectory 'iseberg-core.trx' + if (Test-Path -LiteralPath $resultsPath) { + Remove-Item -LiteralPath $resultsPath + } + + dotnet test $projectPath -c Release -m:1 ` + -p:EnablePowerShellIse=true --filter $filter ` + --logger 'console;verbosity=normal' --logger 'trx;LogFileName=iseberg-core.trx' ` + --results-directory $resultsDirectory ` + --blame-hang --blame-hang-timeout 5min --blame-hang-dump-type none + + [xml]$results = Get-Content -LiteralPath $resultsPath -Raw + if ([int]$results.TestRun.ResultSummary.Counters.executed -eq 0) { + throw "The Iseberg core filter did not execute any tests in $project." + } + } + Write-Host "Iseberg core suite completed in $($elapsed.Elapsed)." +} +finally { + Pop-Location +}