ci: test every pull request and add native Windows ARM64 coverage
This commit is contained in:
1 parent
dcf7f3bb8c
commit
facd48c1b2
8 files changed
+186
-34
No files matched your search
@@ -9,27 +9,14 @@ on:
|
|||||||
default: ""
|
default: ""
|
||||||
workflow_call:
|
workflow_call:
|
||||||
push:
|
push:
|
||||||
# Releases call this entire workflow instead of duplicating branch-push jobs.
|
branches: [main]
|
||||||
branches-ignore: ["release/**"]
|
# Include docs, catalogs, assets and workflow edits: every PR gets test results.
|
||||||
paths:
|
|
||||||
- "**/*.rs"
|
|
||||||
- "scripts/**/*.py"
|
|
||||||
- "**/Cargo.toml"
|
|
||||||
- "Cargo.lock"
|
|
||||||
- "rust-toolchain.toml"
|
|
||||||
- ".github/workflows/linux-lua.yml"
|
|
||||||
- ".github/ci-profile.toml"
|
|
||||||
- ".github/actions/rust-cache/action.yml"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
merge_group:
|
||||||
- "**/*.rs"
|
|
||||||
- "scripts/**/*.py"
|
concurrency:
|
||||||
- "**/Cargo.toml"
|
group: native-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
|
||||||
- "Cargo.lock"
|
cancel-in-progress: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }}
|
||||||
- "rust-toolchain.toml"
|
|
||||||
- ".github/workflows/linux-lua.yml"
|
|
||||||
- ".github/ci-profile.toml"
|
|
||||||
- ".github/actions/rust-cache/action.yml"
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -48,7 +35,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, windows-2022, macos-26, macos-26-intel]
|
os: [ubuntu-24.04, windows-2022, windows-11-arm, macos-26, macos-26-intel]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
timeout-minutes: 120
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
@@ -82,6 +69,17 @@ jobs:
|
|||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
toolchain: "1.97.1"
|
toolchain: "1.97.1"
|
||||||
|
- name: Require a native Windows ARM64 compiler
|
||||||
|
if: matrix.os == 'windows-11-arm'
|
||||||
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -ne 'Arm64') {
|
||||||
|
throw 'The Windows ARM job requires an ARM64 host.'
|
||||||
|
}
|
||||||
|
$compiler = rustc -vV
|
||||||
|
if ($LASTEXITCODE -ne 0 -or $compiler -notcontains 'host: aarch64-pc-windows-msvc') {
|
||||||
|
throw 'The Windows ARM job must compile and run ARM64 tests.'
|
||||||
|
}
|
||||||
- uses: ./.github/actions/rust-cache
|
- uses: ./.github/actions/rust-cache
|
||||||
id: rust-cache
|
id: rust-cache
|
||||||
with:
|
with:
|
||||||
@@ -94,7 +92,10 @@ jobs:
|
|||||||
- name: Prepare pinned Windows console runtime
|
- name: Prepare pinned Windows console runtime
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: ./scripts/prepare-windows-runtime.ps1 -Destination assets/windows/conhost
|
run: |
|
||||||
|
$architecture = if ('${{ runner.arch }}' -eq 'ARM64') { 'arm64' } else { 'x64' }
|
||||||
|
./scripts/prepare-windows-runtime.ps1 -Destination assets/windows/conhost -Architecture $architecture
|
||||||
|
./scripts/tests/windows-runtime.tests.ps1 -Architecture $architecture
|
||||||
- name: Test complete workspace and native harness
|
- name: Test complete workspace and native harness
|
||||||
run: python scripts/ci_native_tests.py
|
run: python scripts/ci_native_tests.py
|
||||||
- name: Check source architecture
|
- name: Check source architecture
|
||||||
|
|||||||
@@ -5,10 +5,46 @@ run-name: >-
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
paths: ["**/*.rs", "**/Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "nebula_app/res/**", "assets/**", "packaging/**", "scripts/**", ".github/workflows/preview-packages.yml"]
|
# Native tests cover every PR; package only when package inputs change.
|
||||||
|
paths:
|
||||||
|
- "**/Cargo.toml"
|
||||||
|
- "Cargo.lock"
|
||||||
|
- "rust-toolchain.toml"
|
||||||
|
- "nebula_app/build.rs"
|
||||||
|
- "nebula_app/build/**"
|
||||||
|
- "nebula_app/res/**"
|
||||||
|
- "nebula_app/windows/**"
|
||||||
|
- "assets/**"
|
||||||
|
- "packaging/**"
|
||||||
|
- "scripts/package*"
|
||||||
|
- "scripts/build-*"
|
||||||
|
- "scripts/installer*"
|
||||||
|
- "scripts/prepare-windows-runtime.ps1"
|
||||||
|
- "scripts/preview_release.py"
|
||||||
|
- "scripts/conformance/**"
|
||||||
|
- "scripts/tests/test_preview_release.py"
|
||||||
|
- ".github/workflows/preview-packages.yml"
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
paths: ["**/*.rs", "**/Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "nebula_app/res/**", "assets/**", "packaging/**", "scripts/**", ".github/workflows/preview-packages.yml"]
|
# Native tests cover every PR; package only when package inputs change.
|
||||||
|
paths:
|
||||||
|
- "**/Cargo.toml"
|
||||||
|
- "Cargo.lock"
|
||||||
|
- "rust-toolchain.toml"
|
||||||
|
- "nebula_app/build.rs"
|
||||||
|
- "nebula_app/build/**"
|
||||||
|
- "nebula_app/res/**"
|
||||||
|
- "nebula_app/windows/**"
|
||||||
|
- "assets/**"
|
||||||
|
- "packaging/**"
|
||||||
|
- "scripts/package*"
|
||||||
|
- "scripts/build-*"
|
||||||
|
- "scripts/installer*"
|
||||||
|
- "scripts/prepare-windows-runtime.ps1"
|
||||||
|
- "scripts/preview_release.py"
|
||||||
|
- "scripts/conformance/**"
|
||||||
|
- "scripts/tests/test_preview_release.py"
|
||||||
|
- ".github/workflows/preview-packages.yml"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
preview_id:
|
preview_id:
|
||||||
@@ -159,6 +195,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-on-failure: true
|
cache-on-failure: true
|
||||||
|
|
||||||
|
- name: Prepare pinned Windows console runtime
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/prepare-windows-runtime.ps1 -Destination assets/windows/conhost
|
||||||
- name: Test workspace natively
|
- name: Test workspace natively
|
||||||
run: cargo test --locked --workspace
|
run: cargo test --locked --workspace
|
||||||
|
|
||||||
@@ -339,6 +378,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cache-on-failure: true
|
cache-on-failure: true
|
||||||
|
|
||||||
|
- name: Prepare pinned Windows console runtime
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/prepare-windows-runtime.ps1 -Destination assets/windows/conhost
|
||||||
- name: Test workspace natively
|
- name: Test workspace natively
|
||||||
run: cargo test --locked --workspace
|
run: cargo test --locked --workspace
|
||||||
|
|
||||||
@@ -497,6 +539,9 @@ jobs:
|
|||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
cache-on-failure: true
|
cache-on-failure: true
|
||||||
|
- name: Prepare pinned Windows console runtime
|
||||||
|
shell: pwsh
|
||||||
|
run: ./scripts/prepare-windows-runtime.ps1 -Destination assets/windows/conhost
|
||||||
- name: Test workspace natively
|
- name: Test workspace natively
|
||||||
run: cargo test --locked --workspace
|
run: cargo test --locked --workspace
|
||||||
- name: Test SSH confirmation and password dialogs
|
- name: Test SSH confirmation and password dialogs
|
||||||
|
|||||||
@@ -101,6 +101,18 @@ Run affected behavior tests and the appropriate real product checks as well:
|
|||||||
cargo check -p nebula --bin pebrel --features gpui-shell --tests --locked
|
cargo check -p nebula --bin pebrel --features gpui-shell --tests --locked
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`Full native tests` runs on every PR and merge-group update, and on `main` pushes.
|
||||||
|
It tests the full workspace on Linux, Windows x64 / ARM64 and both macOS
|
||||||
|
architectures. New commits cancel obsolete PR runs. Package validation has its own
|
||||||
|
input filters and can also be dispatched manually; a package job does not replace
|
||||||
|
the native test suite. These triggers do not configure required status checks.
|
||||||
|
|
||||||
|
GitHub may show **Waiting for approval** for a first-time fork contributor. A
|
||||||
|
maintainer must inspect the submitted changes and approve that workflow run from
|
||||||
|
the Actions page before tests start. Pushing more commits does not remove this
|
||||||
|
GitHub approval requirement; do not run fork code through `pull_request_target`
|
||||||
|
or give it a write token to work around the wait.
|
||||||
|
|
||||||
The isolated i18n test compiles production files, not copied implementations. It
|
The isolated i18n test compiles production files, not copied implementations. It
|
||||||
does not test real window layout, every OS integration, or the full application.
|
does not test real window layout, every OS integration, or the full application.
|
||||||
Existing platform build/package checks still apply. Never turn a metadata-only
|
Existing platform build/package checks still apply. Never turn a metadata-only
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ The bundled conpty.dll and OpenConsole.exe come from the Windows
|
|||||||
Terminal project (github.com/microsoft/terminal), distributed under the
|
Terminal project (github.com/microsoft/terminal), distributed under the
|
||||||
MIT License.
|
MIT License.
|
||||||
|
|
||||||
|
The Windows ARM64 CI runtime is pinned to the Microsoft.Windows.Console.ConPTY
|
||||||
|
NuGet package 1.24.260710001 from Microsoft. Archive and individual redistributable
|
||||||
|
hashes, architecture and source URL are verified by scripts/prepare-windows-runtime.ps1.
|
||||||
|
|
||||||
The GPUI interface layer is built with gpui 0.2.2, developed by Zed
|
The GPUI interface layer is built with gpui 0.2.2, developed by Zed
|
||||||
Industries (github.com/zed-industries/zed), and gpui-component 0.5.1,
|
Industries (github.com/zed-industries/zed), and gpui-component 0.5.1,
|
||||||
developed by Longbridge (github.com/longbridge/gpui-component). Both are
|
developed by Longbridge (github.com/longbridge/gpui-component). Both are
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)][string] $Destination,
|
[Parameter(Mandatory = $true)][string] $Destination,
|
||||||
[string] $ArchivePath
|
[string] $ArchivePath,
|
||||||
|
[ValidateSet('x64', 'arm64')][string] $Architecture = 'x64'
|
||||||
)
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
@@ -16,9 +17,44 @@ $expected = [ordered]@{
|
|||||||
'conpty.dll' = '375BFB0479B6C53836AB307E3F9FD17BEDBD733F2E9690943D0F12E72FB80777'
|
'conpty.dll' = '375BFB0479B6C53836AB307E3F9FD17BEDBD733F2E9690943D0F12E72FB80777'
|
||||||
'OpenConsole.exe' = '55B18996761C88C351820E82508E05AB0EC2194AEEAD20724FDFAEEDEC076EF4'
|
'OpenConsole.exe' = '55B18996761C88C351820E82508E05AB0EC2194AEEAD20724FDFAEEDEC076EF4'
|
||||||
}
|
}
|
||||||
|
$entries = @{
|
||||||
|
'conpty.dll' = 'runtime\conpty.dll'
|
||||||
|
'OpenConsole.exe' = 'runtime\OpenConsole.exe'
|
||||||
|
}
|
||||||
|
$archiveName = 'pebrel-conpty-source-v1.5.0.zip'
|
||||||
|
$machine = 0x8664
|
||||||
|
if ($Architecture -eq 'arm64') {
|
||||||
|
# Microsoft MIT-licensed redistributables; the NuGet declares build 17763+.
|
||||||
|
# Keep the previously shipped x64 runtime unchanged.
|
||||||
|
$sourceUrl = 'https://api.nuget.org/v3-flatcontainer/microsoft.windows.console.conpty/1.24.260710001/microsoft.windows.console.conpty.1.24.260710001.nupkg'
|
||||||
|
$archiveName = 'pebrel-conpty-source-1.24.260710001.nupkg'
|
||||||
|
$archiveHash = '175640566A3B59C4B132070EE96C2C77E5AB7EDD2E92732A5EB3610BBF63D90E'
|
||||||
|
$expected = [ordered]@{
|
||||||
|
'conpty.dll' = 'DB3D173640B172BAFD42D5B541B638A9AEEC1C7D0E40DD636BF02822A32C912C'
|
||||||
|
'OpenConsole.exe' = 'ED7622FD0D3BEDC9AB9F122F5E58EDF0DEF9E7999224F52DD395BA9F54EDBE09'
|
||||||
|
}
|
||||||
|
$entries = @{
|
||||||
|
'conpty.dll' = 'runtimes/win-arm64/native/conpty.dll'
|
||||||
|
'OpenConsole.exe' = 'build/native/runtimes/arm64/OpenConsole.exe'
|
||||||
|
}
|
||||||
|
$machine = 0xAA64
|
||||||
|
}
|
||||||
|
|
||||||
|
function Assert-RuntimeMachine([string] $Path) {
|
||||||
|
$bytes = [IO.File]::ReadAllBytes($Path)
|
||||||
|
if ($bytes.Length -lt 64 -or $bytes[0] -ne 0x4D -or $bytes[1] -ne 0x5A) {
|
||||||
|
throw "Invalid PE runtime: $Path"
|
||||||
|
}
|
||||||
|
$offset = [BitConverter]::ToInt32($bytes, 0x3C)
|
||||||
|
if ($offset -lt 64 -or $offset -gt $bytes.Length - 6 -or
|
||||||
|
[BitConverter]::ToUInt32($bytes, $offset) -ne 0x4550 -or
|
||||||
|
[BitConverter]::ToUInt16($bytes, $offset + 4) -ne $machine) {
|
||||||
|
throw "Runtime PE architecture does not match $Architecture`: $Path"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ([string]::IsNullOrWhiteSpace($ArchivePath)) {
|
if ([string]::IsNullOrWhiteSpace($ArchivePath)) {
|
||||||
$ArchivePath = Join-Path ([System.IO.Path]::GetTempPath()) 'pebrel-conpty-source-v1.5.0.zip'
|
$ArchivePath = Join-Path ([System.IO.Path]::GetTempPath()) $archiveName
|
||||||
if (-not (Test-Path -LiteralPath $ArchivePath -PathType Leaf)) {
|
if (-not (Test-Path -LiteralPath $ArchivePath -PathType Leaf)) {
|
||||||
Invoke-WebRequest -Uri $sourceUrl -OutFile $ArchivePath -UseBasicParsing -TimeoutSec 120
|
Invoke-WebRequest -Uri $sourceUrl -OutFile $ArchivePath -UseBasicParsing -TimeoutSec 120
|
||||||
}
|
}
|
||||||
@@ -35,10 +71,11 @@ try {
|
|||||||
$target = Join-Path $Destination $name
|
$target = Join-Path $Destination $name
|
||||||
if ((Test-Path -LiteralPath $target -PathType Leaf) -and
|
if ((Test-Path -LiteralPath $target -PathType Leaf) -and
|
||||||
(Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash -eq $expected[$name]) {
|
(Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash -eq $expected[$name]) {
|
||||||
|
Assert-RuntimeMachine $target
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$entry = $archive.GetEntry("runtime\$name")
|
$entry = $archive.GetEntry($entries[$name])
|
||||||
if ($null -eq $entry) { throw "Runtime archive is missing runtime/$name" }
|
if ($null -eq $entry) { throw "Runtime archive is missing $($entries[$name])" }
|
||||||
$temporary = "$target.$([guid]::NewGuid().ToString('N')).tmp"
|
$temporary = "$target.$([guid]::NewGuid().ToString('N')).tmp"
|
||||||
try {
|
try {
|
||||||
$inputStream = $entry.Open()
|
$inputStream = $entry.Open()
|
||||||
@@ -49,6 +86,7 @@ try {
|
|||||||
if ((Get-FileHash -LiteralPath $temporary -Algorithm SHA256).Hash -ne $expected[$name]) {
|
if ((Get-FileHash -LiteralPath $temporary -Algorithm SHA256).Hash -ne $expected[$name]) {
|
||||||
throw "The pinned $name failed SHA256 verification."
|
throw "The pinned $name failed SHA256 verification."
|
||||||
}
|
}
|
||||||
|
Assert-RuntimeMachine $temporary
|
||||||
Move-Item -LiteralPath $temporary -Destination $target -Force
|
Move-Item -LiteralPath $temporary -Destination $target -Force
|
||||||
} finally {
|
} finally {
|
||||||
if (Test-Path -LiteralPath $temporary) { Remove-Item -LiteralPath $temporary }
|
if (Test-Path -LiteralPath $temporary) { Remove-Item -LiteralPath $temporary }
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import tomllib
|
import tomllib
|
||||||
import unittest
|
import unittest
|
||||||
@@ -10,6 +11,36 @@ from scripts.ci_native_tests import main, native_commands
|
|||||||
|
|
||||||
|
|
||||||
class NativeSuiteTests(unittest.TestCase):
|
class NativeSuiteTests(unittest.TestCase):
|
||||||
|
def test_every_pr_and_merge_group_runs_without_path_exclusions(self):
|
||||||
|
root = Path(__file__).resolve().parents[2]
|
||||||
|
workflow = (root / ".github/workflows/linux-lua.yml").read_text()
|
||||||
|
events = workflow.split("\non:\n", 1)[1].split("\nconcurrency:", 1)[0]
|
||||||
|
for event in ("pull_request", "merge_group"):
|
||||||
|
declaration = re.search(rf"^ {event}:(.*?)(?=^ [a-z_]+:|\Z)", events, re.M | re.S)
|
||||||
|
self.assertIsNotNone(declaration)
|
||||||
|
self.assertNotIn("paths", declaration.group(1))
|
||||||
|
self.assertNotIn("branches", declaration.group(1))
|
||||||
|
self.assertNotIn("types", declaration.group(1))
|
||||||
|
self.assertIn("branches: [main]", events)
|
||||||
|
self.assertNotIn("branches-ignore", events)
|
||||||
|
self.assertNotIn("pull_request_target", workflow)
|
||||||
|
self.assertNotIn("contents: write", workflow)
|
||||||
|
self.assertIn("cancel-in-progress: ${{ github.event_name == 'pull_request'", workflow)
|
||||||
|
|
||||||
|
def test_arm_job_requires_native_execution_and_matching_console_runtime(self):
|
||||||
|
root = Path(__file__).resolve().parents[2]
|
||||||
|
workflow = (root / ".github/workflows/linux-lua.yml").read_text()
|
||||||
|
self.assertIn("windows-11-arm", workflow)
|
||||||
|
self.assertIn("host: aarch64-pc-windows-msvc", workflow)
|
||||||
|
self.assertIn("OSArchitecture -ne 'Arm64'", workflow)
|
||||||
|
self.assertIn("-Architecture $architecture", workflow)
|
||||||
|
self.assertLess(workflow.index("Prepare pinned Windows console runtime"),
|
||||||
|
workflow.index("Test complete workspace"))
|
||||||
|
preview = (root / ".github/workflows/preview-packages.yml").read_text()
|
||||||
|
windows = preview.split("\n windows:\n", 1)[1].split("\n aggregate:", 1)[0]
|
||||||
|
self.assertLess(windows.index("prepare-windows-runtime.ps1"),
|
||||||
|
windows.index("cargo test --locked --workspace"))
|
||||||
|
|
||||||
def test_full_workspace_and_interactions_share_one_unfiltered_invocation(self):
|
def test_full_workspace_and_interactions_share_one_unfiltered_invocation(self):
|
||||||
rust = [command for command in native_commands() if command[:2] == ["cargo", "test"]]
|
rust = [command for command in native_commands() if command[:2] == ["cargo", "test"]]
|
||||||
self.assertEqual(len(rust), 1)
|
self.assertEqual(len(rust), 1)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class StableReleaseTests(unittest.TestCase):
|
|||||||
native = workflow.split(" native-tests:\n", 1)[1].split("\n linux:\n", 1)[0]
|
native = workflow.split(" native-tests:\n", 1)[1].split("\n linux:\n", 1)[0]
|
||||||
self.assertIn("uses: ./.github/workflows/linux-lua.yml", native)
|
self.assertIn("uses: ./.github/workflows/linux-lua.yml", native)
|
||||||
shared = (root / ".github/workflows/linux-lua.yml").read_text(encoding="utf-8")
|
shared = (root / ".github/workflows/linux-lua.yml").read_text(encoding="utf-8")
|
||||||
for platform in ("ubuntu-24.04", "windows-2022", "macos-26", "macos-26-intel"):
|
for platform in ("ubuntu-24.04", "windows-2022", "windows-11-arm", "macos-26", "macos-26-intel"):
|
||||||
self.assertIn(platform, shared)
|
self.assertIn(platform, shared)
|
||||||
self.assertIn("workflow_call:", shared)
|
self.assertIn("workflow_call:", shared)
|
||||||
self.assertIn("run: python scripts/ci_native_tests.py", shared)
|
self.assertIn("run: python scripts/ci_native_tests.py", shared)
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param([Parameter(Mandatory = $true)][string] $ArchivePath)
|
param(
|
||||||
|
[string] $ArchivePath,
|
||||||
|
[ValidateSet('x64', 'arm64')][string] $Architecture = 'x64'
|
||||||
|
)
|
||||||
|
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$prepare = Join-Path $PSScriptRoot '../prepare-windows-runtime.ps1'
|
$prepare = Join-Path $PSScriptRoot '../prepare-windows-runtime.ps1'
|
||||||
@@ -7,22 +10,40 @@ $root = Join-Path ([IO.Path]::GetTempPath()) "pebrel-runtime-test-$([guid]::NewG
|
|||||||
New-Item -ItemType Directory -Path $root | Out-Null
|
New-Item -ItemType Directory -Path $root | Out-Null
|
||||||
try {
|
try {
|
||||||
$destination = Join-Path $root 'runtime'
|
$destination = Join-Path $root 'runtime'
|
||||||
& $prepare -Destination $destination -ArchivePath $ArchivePath
|
& $prepare -Destination $destination -ArchivePath $ArchivePath -Architecture $Architecture
|
||||||
$before = @(Get-ChildItem $destination | Sort-Object Name | ForEach-Object { $_.LastWriteTimeUtc.Ticks })
|
$before = @(Get-ChildItem $destination | Sort-Object Name | ForEach-Object { $_.LastWriteTimeUtc.Ticks })
|
||||||
& $prepare -Destination $destination -ArchivePath $ArchivePath
|
& $prepare -Destination $destination -ArchivePath $ArchivePath -Architecture $Architecture
|
||||||
$after = @(Get-ChildItem $destination | Sort-Object Name | ForEach-Object { $_.LastWriteTimeUtc.Ticks })
|
$after = @(Get-ChildItem $destination | Sort-Object Name | ForEach-Object { $_.LastWriteTimeUtc.Ticks })
|
||||||
if (@(Compare-Object $before $after).Count -ne 0) { throw 'Verified runtime files were unnecessarily replaced.' }
|
if (@(Compare-Object $before $after).Count -ne 0) { throw 'Verified runtime files were unnecessarily replaced.' }
|
||||||
if (@(Get-ChildItem $destination).Count -ne 2) { throw 'Unexpected files were extracted.' }
|
if (@(Get-ChildItem $destination).Count -ne 2) { throw 'Unexpected files were extracted.' }
|
||||||
|
$dll = Join-Path $destination 'conpty.dll'
|
||||||
|
$originalHash = (Get-FileHash $dll -Algorithm SHA256).Hash
|
||||||
|
[IO.File]::WriteAllBytes($dll, [byte[]]@(0, 1, 2, 3))
|
||||||
|
& $prepare -Destination $destination -ArchivePath $ArchivePath -Architecture $Architecture
|
||||||
|
if ((Get-FileHash $dll -Algorithm SHA256).Hash -ne $originalHash) {
|
||||||
|
throw 'A corrupt or wrong-architecture installed runtime was reused.'
|
||||||
|
}
|
||||||
|
|
||||||
$invalid = Join-Path $root 'different.zip'
|
$invalid = Join-Path $root 'different.zip'
|
||||||
[IO.File]::WriteAllBytes($invalid, [byte[]]@(80, 75, 0, 0))
|
[IO.File]::WriteAllBytes($invalid, [byte[]]@(80, 75, 0, 0))
|
||||||
$rejected = $false
|
$rejected = $false
|
||||||
try { & $prepare -Destination (Join-Path $root 'rejected') -ArchivePath $invalid }
|
try { & $prepare -Destination (Join-Path $root 'rejected') -ArchivePath $invalid -Architecture $Architecture }
|
||||||
catch {
|
catch {
|
||||||
if ($_.Exception.Message -notlike '*SHA256 verification*') { throw }
|
if ($_.Exception.Message -notlike '*SHA256 verification*') { throw }
|
||||||
$rejected = $true
|
$rejected = $true
|
||||||
}
|
}
|
||||||
if (-not $rejected) { throw 'A different archive was accepted.' }
|
if (-not $rejected) { throw 'A different archive was accepted.' }
|
||||||
if (Test-Path (Join-Path $root 'rejected')) { throw 'Files were created before archive verification.' }
|
if (Test-Path (Join-Path $root 'rejected')) { throw 'Files were created before archive verification.' }
|
||||||
Write-Output 'windows-runtime.tests.ps1: PASS (pinned files, incremental reuse, hash mismatch)'
|
if ($ArchivePath) {
|
||||||
|
$otherArchitecture = if ($Architecture -eq 'arm64') { 'x64' } else { 'arm64' }
|
||||||
|
$rejected = $false
|
||||||
|
try { & $prepare -Destination (Join-Path $root 'wrong-arch') -ArchivePath $ArchivePath -Architecture $otherArchitecture }
|
||||||
|
catch {
|
||||||
|
if ($_.Exception.Message -notlike '*SHA256 verification*') { throw }
|
||||||
|
$rejected = $true
|
||||||
|
}
|
||||||
|
if (-not $rejected) { throw 'An archive for the other architecture was accepted.' }
|
||||||
|
if (Test-Path (Join-Path $root 'wrong-arch')) { throw 'A wrong-architecture archive was extracted.' }
|
||||||
|
}
|
||||||
|
Write-Output "windows-runtime.tests.ps1: PASS ($Architecture pinned files, reuse, repair, rejected archives)"
|
||||||
} finally { Remove-Item -LiteralPath $root -Recurse -Force }
|
} finally { Remove-Item -LiteralPath $root -Recurse -Force }
|
||||||
Reference in new issue
Block a user