返回 CodeWhale
update-user-path.tests.ps1
根目录 / scripts / installer / update-user-path.tests.ps1
1 $ErrorActionPreference = 'Stop'
2 Set-StrictMode -Version Latest
3
4 . "$PSScriptRoot\update-user-path.ps1"
5
6 function Assert-Equal {
7 param(
8 [AllowNull()]
9 $Expected,
10
11 [AllowNull()]
12 $Actual,
13
14 [Parameter(Mandatory = $true)]
15 [string] $Because
16 )
17
18 if (-not [object]::Equals($Expected, $Actual)) {
19 throw "$Because`nExpected: <$Expected>`nActual: <$Actual>"
20 }
21 }
22
23 $entry = 'C:\CodeWhalePathTest\bin'
24 $longPath = ((1..80) | ForEach-Object { 'C:\CWCanary\DevelopmentTool{0:D4}\bin' -f $_ }) -join ';'
25 if ($longPath.Length -le 1800) {
26 throw "The long-PATH fixture is too short: $($longPath.Length)."
27 }
28
29 $addedToEmpty = Get-UpdatedUserPath `
30 -Current '' `
31 -RequestedOperation Add `
32 -RequestedEntry $entry
33 Assert-Equal $entry $addedToEmpty 'Adding to a missing or empty PATH must create only the requested entry.'
34
35 $added = Get-UpdatedUserPath `
36 -Current $longPath `
37 -RequestedOperation Add `
38 -RequestedEntry $entry
39 Assert-Equal "$longPath;$entry" $added 'Adding to a long PATH must preserve every existing character.'
40
41 $expanded = '%USERPROFILE%\bin;C:\Tools'
42 $expandedAdded = Get-UpdatedUserPath `
43 -Current $expanded `
44 -RequestedOperation Add `
45 -RequestedEntry $entry
46 Assert-Equal "$expanded;$entry" $expandedAdded 'Expandable variable references must remain unexpanded.'
47
48 $alreadyPresent = "$longPath;$($entry.ToUpperInvariant())\"
49 $unchanged = Get-UpdatedUserPath `
50 -Current $alreadyPresent `
51 -RequestedOperation Add `
52 -RequestedEntry $entry
53 Assert-Equal $alreadyPresent $unchanged 'Adding must be idempotent across case and a trailing slash.'
54
55 $substringPath = 'C:\CodeWhalePathTest\bin-tools;C:\Other'
56 $substringAdded = Get-UpdatedUserPath `
57 -Current $substringPath `
58 -RequestedOperation Add `
59 -RequestedEntry $entry
60 Assert-Equal "$substringPath;$entry" $substringAdded 'A substring must not count as an exact PATH entry.'
61
62 $trailingDelimiter = 'C:\One;C:\Two;'
63 $trailingAdded = Get-UpdatedUserPath `
64 -Current $trailingDelimiter `
65 -RequestedOperation Add `
66 -RequestedEntry $entry
67 Assert-Equal "$trailingDelimiter$entry" $trailingAdded 'Adding after a trailing delimiter must not create a blank entry.'
68
69 $removalSource = "C:\Before;$entry;C:\After"
70 $removed = Get-UpdatedUserPath `
71 -Current $removalSource `
72 -RequestedOperation Remove `
73 -RequestedEntry $entry
74 Assert-Equal 'C:\Before;C:\After' $removed 'Removing must delete only the exact CodeWhale entry.'
75
76 $duplicateSource = "$entry;C:\Keep;$($entry.ToUpperInvariant())\"
77 $duplicatesRemoved = Get-UpdatedUserPath `
78 -Current $duplicateSource `
79 -RequestedOperation Remove `
80 -RequestedEntry $entry
81 Assert-Equal 'C:\Keep' $duplicatesRemoved 'Uninstall must remove all equivalent CodeWhale entries.'
82
83 $unrelated = 'C:\One;C:\CodeWhalePathTest\bin-tools;C:\Two'
84 $unrelatedResult = Get-UpdatedUserPath `
85 -Current $unrelated `
86 -RequestedOperation Remove `
87 -RequestedEntry $entry
88 Assert-Equal $unrelated $unrelatedResult 'Removing an absent entry must leave the PATH byte-for-byte unchanged.'
89
90 if ([System.Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT) {
91 $testKeyPath = "Software\CodeWhale\Tests\UserPath-$PID-$([guid]::NewGuid().ToString('N'))"
92 $testKey = [Microsoft.Win32.Registry]::CurrentUser.CreateSubKey($testKeyPath)
93 if ($null -eq $testKey) {
94 throw 'Could not create the isolated registry test key.'
95 }
96
97 try {
98 $testKey.SetValue('Path', $longPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
99 $changed = Set-RegistryPathEntry `
100 -RegistryKey $testKey `
101 -RequestedOperation Add `
102 -RequestedEntry $entry
103 Assert-Equal $true $changed 'The registry helper must report a long PATH update.'
104
105 $raw = [string] $testKey.GetValue(
106 'Path',
107 $null,
108 [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
109 )
110 Assert-Equal "$longPath;$entry" $raw 'The registry helper must not truncate a long PATH.'
111 Assert-Equal `
112 ([Microsoft.Win32.RegistryValueKind]::ExpandString) `
113 ($testKey.GetValueKind('Path')) `
114 'The registry helper must preserve REG_EXPAND_SZ.'
115
116 $changedAgain = Set-RegistryPathEntry `
117 -RegistryKey $testKey `
118 -RequestedOperation Add `
119 -RequestedEntry $entry
120 Assert-Equal $false $changedAgain 'A repeated install must not rewrite the registry value.'
121
122 $removedFromRegistry = Set-RegistryPathEntry `
123 -RegistryKey $testKey `
124 -RequestedOperation Remove `
125 -RequestedEntry $entry
126 Assert-Equal $true $removedFromRegistry 'The registry helper must remove the installed entry.'
127
128 $restored = [string] $testKey.GetValue(
129 'Path',
130 $null,
131 [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames
132 )
133 Assert-Equal $longPath $restored 'Install followed by uninstall must restore the long PATH exactly.'
134
135 $testKey.SetValue('Path', 'C:\Plain', [Microsoft.Win32.RegistryValueKind]::String)
136 [void] (Set-RegistryPathEntry `
137 -RegistryKey $testKey `
138 -RequestedOperation Add `
139 -RequestedEntry $entry)
140 Assert-Equal `
141 ([Microsoft.Win32.RegistryValueKind]::String) `
142 ($testKey.GetValueKind('Path')) `
143 'The registry helper must preserve REG_SZ.'
144
145 $testKey.DeleteValue('Path')
146 $missingRemoval = Set-RegistryPathEntry `
147 -RegistryKey $testKey `
148 -RequestedOperation Remove `
149 -RequestedEntry $entry
150 Assert-Equal $false $missingRemoval 'Removing from a missing PATH must be a no-op.'
151 Assert-Equal `
152 $false `
153 (@($testKey.GetValueNames()) -contains 'Path') `
154 'A no-op uninstall must not create a missing PATH value.'
155 }
156 finally {
157 $testKey.Close()
158 [Microsoft.Win32.Registry]::CurrentUser.DeleteSubKeyTree($testKeyPath, $false)
159 }
160 }
161
162 Write-Host 'Windows installer PATH helper tests passed.'
163
163 lines Plain Text