Skip to content

Commit 7bdc3d5

Browse files
committed
pacman: exercise Windows filesystem edge cases
1 parent 780c450 commit 7bdc3d5

2 files changed

Lines changed: 184 additions & 28 deletions

File tree

.github/workflows/msys-pacman-source.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,7 @@ jobs:
5454
shell: pwsh
5555
run: |
5656
./tests/pacman/msys-runtime-smoke.ps1 `
57+
-WorkDirectory (Join-Path $env:RUNNER_TEMP "vitasdk-ñ-日本語 path") `
5758
-PacmanExecutable (Join-Path $env:RUNNER_TEMP "vitasdk-pacman/pacman.exe") `
58-
-RuntimeDll (Join-Path $env:RUNNER_TEMP "vitasdk-pacman/msys-2.0.dll")
59+
-RuntimeDll (Join-Path $env:RUNNER_TEMP "vitasdk-pacman/msys-2.0.dll") `
60+
-Extended

tests/pacman/msys-runtime-smoke.ps1

Lines changed: 181 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
param(
22
[string]$WorkDirectory = (Join-Path $env:TEMP "vitasdk-msys-pacman-smoke"),
33
[string]$PacmanExecutable = "",
4-
[string]$RuntimeDll = ""
4+
[string]$RuntimeDll = "",
5+
[switch]$Extended
56
)
67

78
$ErrorActionPreference = "Stop"
@@ -30,6 +31,82 @@ function Invoke-Checked([string]$Program, [string[]]$Arguments) {
3031
}
3132
}
3233

34+
function Invoke-ExpectedFailure([string]$Program, [string[]]$Arguments, [string]$Description) {
35+
& $Program @Arguments
36+
if ($LASTEXITCODE -eq 0) {
37+
throw "operation unexpectedly succeeded: ${Description}"
38+
}
39+
Write-Host "Expected failure passed: ${Description}"
40+
}
41+
42+
function Write-PackageMetadata(
43+
[string]$Root,
44+
[string]$Name,
45+
[string]$Version,
46+
[string]$Description
47+
) {
48+
[IO.File]::WriteAllText((Join-Path $Root ".PKGINFO"), (@(
49+
"pkgname = ${Name}",
50+
"pkgbase = ${Name}",
51+
"pkgver = ${Version}",
52+
"pkgdesc = ${Description}",
53+
"builddate = 0",
54+
"packager = VitaSDK CI",
55+
"size = 4096",
56+
"arch = x86_64",
57+
"license = MIT"
58+
) -join "`n") + "`n")
59+
}
60+
61+
function New-ProbePackage(
62+
[string]$Root,
63+
[string]$Output,
64+
[string]$Name,
65+
[string]$Version,
66+
[System.Collections.IDictionary]$Files
67+
) {
68+
if (Test-Path $Root) {
69+
Remove-Item -Recurse -Force $Root
70+
}
71+
New-Item -ItemType Directory -Force -Path $Root | Out-Null
72+
Write-PackageMetadata $Root $Name $Version "VitaSDK MSYS Windows filesystem probe"
73+
74+
$archiveEntries = @(".PKGINFO")
75+
foreach ($entry in ($Files.GetEnumerator() | Sort-Object Key)) {
76+
$filePath = Join-Path $Root $entry.Key
77+
New-Item -ItemType Directory -Force -Path (Split-Path $filePath) | Out-Null
78+
[IO.File]::WriteAllText($filePath, $entry.Value)
79+
$archiveEntries += $entry.Key
80+
}
81+
82+
Invoke-Checked "tar.exe" (@("-cJf", $Output, "-C", $Root) + $archiveEntries)
83+
}
84+
85+
function New-CaseCollisionPackage([string]$Root, [string]$Output) {
86+
if (Test-Path $Root) {
87+
Remove-Item -Recurse -Force $Root
88+
}
89+
$upperRoot = Join-Path $Root "upper"
90+
$lowerRoot = Join-Path $Root "lower"
91+
New-Item -ItemType Directory -Force -Path $upperRoot, $lowerRoot | Out-Null
92+
Write-PackageMetadata $Root "vitasdk-msys-case-collision" "1.0-1" `
93+
"Case-insensitive path collision probe"
94+
[IO.File]::WriteAllText((Join-Path $upperRoot "Collision.h"), "upper`n")
95+
[IO.File]::WriteAllText((Join-Path $lowerRoot "collision.h"), "lower`n")
96+
97+
# The source paths are distinct on Windows. Rewrite them only while adding
98+
# them to the archive so the payload contains two case-folding equivalents.
99+
Invoke-Checked "tar.exe" @(
100+
"-cJf", $Output,
101+
"-s", "|^upper/|arm-vita-eabi/include/case-probe/|",
102+
"-s", "|^lower/|arm-vita-eabi/include/case-probe/|",
103+
"-C", $Root,
104+
".PKGINFO",
105+
"upper/Collision.h",
106+
"lower/collision.h"
107+
)
108+
}
109+
33110
if (Test-Path $WorkDirectory) {
34111
Remove-Item -Recurse -Force $WorkDirectory
35112
}
@@ -42,8 +119,12 @@ $dbPath = Join-Path $sdkRoot "var/lib/pacman"
42119
$cachePath = Join-Path $sdkRoot "var/cache/pacman/pkg"
43120
$logPath = Join-Path $sdkRoot "var/log/pacman.log"
44121
$configPath = Join-Path $sdkRoot "etc/pacman.conf"
45-
$packageRoot = Join-Path $WorkDirectory "package"
122+
$packageRoot = Join-Path $WorkDirectory "package-v1"
46123
$packagePath = Join-Path $WorkDirectory "vitasdk-msys-probe-1.0-1-any.pkg.tar.xz"
124+
$packageV2Root = Join-Path $WorkDirectory "package-v2"
125+
$packageV2Path = Join-Path $WorkDirectory "vitasdk-msys-probe-2.0-1-any.pkg.tar.xz"
126+
$collisionRoot = Join-Path $WorkDirectory "case-collision-package"
127+
$collisionPath = Join-Path $WorkDirectory "vitasdk-msys-case-collision-1.0-1-any.pkg.tar.xz"
47128

48129
@(
49130
$downloads,
@@ -52,8 +133,7 @@ $packagePath = Join-Path $WorkDirectory "vitasdk-msys-probe-1.0-1-any.pkg.tar.xz
52133
$dbPath,
53134
$cachePath,
54135
(Split-Path $logPath),
55-
(Split-Path $configPath),
56-
(Join-Path $packageRoot "arm-vita-eabi/include")
136+
(Split-Path $configPath)
57137
) | ForEach-Object { New-Item -ItemType Directory -Force -Path $_ | Out-Null }
58138

59139
if (($PacmanExecutable -eq "") -xor ($RuntimeDll -eq "")) {
@@ -99,27 +179,26 @@ if ($runtimeFiles.Count -ne 2) {
99179
"CheckSpace"
100180
) -join "`n") + "`n")
101181

102-
# Pacman package metadata is a Unix text format. Force LF even on Windows.
103-
[IO.File]::WriteAllText((Join-Path $packageRoot ".PKGINFO"), (@(
104-
"pkgname = vitasdk-msys-probe",
105-
"pkgbase = vitasdk-msys-probe",
106-
"pkgver = 1.0-1",
107-
"pkgdesc = VitaSDK MSYS runtime smoke package",
108-
"builddate = 0",
109-
"packager = VitaSDK CI",
110-
"size = 6",
111-
"arch = x86_64",
112-
"license = MIT"
113-
) -join "`n") + "`n")
114-
[IO.File]::WriteAllText(
115-
(Join-Path $packageRoot "arm-vita-eabi/include/msys-probe.h"),
116-
"probe`n"
117-
)
118-
Invoke-Checked "tar.exe" @(
119-
"-cJf", $packagePath,
120-
"-C", $packageRoot,
121-
".PKGINFO", "arm-vita-eabi/include/msys-probe.h"
122-
)
182+
$probeRelativePath = "arm-vita-eabi/include/msys-probe.h"
183+
$utf8RelativePath = "arm-vita-eabi/include/prueba-ñ-日本語.h"
184+
$replaceRelativePath = "arm-vita-eabi/include/replace-on-upgrade.h"
185+
$removedRelativePath = "arm-vita-eabi/include/remove-on-upgrade.h"
186+
$addedRelativePath = "arm-vita-eabi/include/added-on-upgrade.h"
187+
$longSegments = 1..6 | ForEach-Object {
188+
"segment-${_}-" + [string]::new([char]120, 24)
189+
}
190+
$longRelativePath = "arm-vita-eabi/include/" + ($longSegments -join "/") + "/long-probe.h"
191+
192+
$packageFiles = [ordered]@{
193+
$probeRelativePath = "probe`n"
194+
}
195+
if ($Extended) {
196+
$packageFiles[$utf8RelativePath] = "UTF-8 probe`n"
197+
$packageFiles[$longRelativePath] = "long path probe`n"
198+
$packageFiles[$replaceRelativePath] = "version 1`n"
199+
$packageFiles[$removedRelativePath] = "removed by upgrade`n"
200+
}
201+
New-ProbePackage $packageRoot $packagePath "vitasdk-msys-probe" "1.0-1" $packageFiles
123202

124203
$pacman = Join-Path $pacmanBin "pacman.exe"
125204
$commonArguments = @(
@@ -142,11 +221,69 @@ try {
142221
)
143222
Invoke-Checked $pacman @($commonArguments + @("--query", "vitasdk-msys-probe"))
144223

145-
$installedFile = Join-Path $sdkRoot "arm-vita-eabi/include/msys-probe.h"
224+
$installedFile = Join-Path $sdkRoot $probeRelativePath
146225
if (-not (Test-Path $installedFile)) {
147226
throw "package payload was not installed"
148227
}
149228

229+
if ($Extended) {
230+
foreach ($relativePath in @(
231+
$utf8RelativePath,
232+
$longRelativePath,
233+
$replaceRelativePath,
234+
$removedRelativePath
235+
)) {
236+
if (-not (Test-Path (Join-Path $sdkRoot $relativePath))) {
237+
throw "extended package payload was not installed: ${relativePath}"
238+
}
239+
}
240+
241+
$lockPath = Join-Path $dbPath "db.lck"
242+
[IO.File]::WriteAllText($lockPath, "locked by VitaSDK smoke test`n")
243+
try {
244+
Invoke-ExpectedFailure $pacman ($commonArguments + @(
245+
"--remove", "--noscriptlet", "--noconfirm", "vitasdk-msys-probe"
246+
)) "transaction while the SDK database is locked"
247+
if (-not (Test-Path $installedFile)) {
248+
throw "locked transaction modified the installed package"
249+
}
250+
}
251+
finally {
252+
Remove-Item -Force $lockPath
253+
}
254+
255+
$packageV2Files = [ordered]@{
256+
$probeRelativePath = "probe version 2`n"
257+
$utf8RelativePath = "UTF-8 probe version 2`n"
258+
$longRelativePath = "long path probe version 2`n"
259+
$replaceRelativePath = "version 2`n"
260+
$addedRelativePath = "added by upgrade`n"
261+
}
262+
New-ProbePackage $packageV2Root $packageV2Path `
263+
"vitasdk-msys-probe" "2.0-1" $packageV2Files
264+
Invoke-Checked $pacman @(
265+
$commonArguments + @(
266+
"--upgrade", "--noscriptlet", "--noconfirm", (Get-MixedPath $packageV2Path)
267+
)
268+
)
269+
Invoke-Checked $pacman @($commonArguments + @("--query", "vitasdk-msys-probe"))
270+
271+
if ([IO.File]::ReadAllText((Join-Path $sdkRoot $replaceRelativePath)) -ne "version 2`n") {
272+
throw "upgrade did not replace an existing file"
273+
}
274+
if (Test-Path (Join-Path $sdkRoot $removedRelativePath)) {
275+
throw "upgrade did not delete a file removed from the new package"
276+
}
277+
if (-not (Test-Path (Join-Path $sdkRoot $addedRelativePath))) {
278+
throw "upgrade did not install its new file"
279+
}
280+
281+
New-CaseCollisionPackage $collisionRoot $collisionPath
282+
Invoke-ExpectedFailure $pacman ($commonArguments + @(
283+
"--upgrade", "--noscriptlet", "--noconfirm", (Get-MixedPath $collisionPath)
284+
)) "package containing case-insensitive duplicate paths"
285+
}
286+
150287
Invoke-Checked $pacman @(
151288
$commonArguments + @(
152289
"--remove", "--noscriptlet", "--noconfirm", "vitasdk-msys-probe"
@@ -155,9 +292,26 @@ try {
155292
if (Test-Path $installedFile) {
156293
throw "package payload remains after removal"
157294
}
295+
if ($Extended) {
296+
foreach ($relativePath in @(
297+
$utf8RelativePath,
298+
$longRelativePath,
299+
$replaceRelativePath,
300+
$addedRelativePath
301+
)) {
302+
if (Test-Path (Join-Path $sdkRoot $relativePath)) {
303+
throw "extended payload remains after removal: ${relativePath}"
304+
}
305+
}
306+
}
158307
}
159308
finally {
160309
$env:PATH = $savedPath
161310
}
162311

163-
Write-Host "MSYS pacman two-file runtime smoke test passed"
312+
if ($Extended) {
313+
Write-Host "MSYS pacman extended Windows filesystem smoke test passed"
314+
}
315+
else {
316+
Write-Host "MSYS pacman two-file runtime smoke test passed"
317+
}

0 commit comments

Comments
 (0)