tests/Coreutils.Conflicts.Tests.ps1
|
BeforeAll { . "$PSScriptRoot/../Private/Test-DFToolSchema.ps1" . "$PSScriptRoot/../Private/Expand-DFXdgPath.ps1" . "$PSScriptRoot/../Private/Import-DFToolDb.ps1" $script:Coreutils = (Get-Content "$PSScriptRoot/data/coreutils-commands.json" -Raw | ConvertFrom-Json).commands # Collisions we have consciously accepted. Each entry is a decision, not an # oversight: DotForge ships the alias knowing coreutils shadows it on machines # where that utility is enabled, and Get-DFCommandConflict tells the user at # runtime so they can pick a side. # # Adding a name here is the whole point of this tripwire — it should be a # deliberate act, with a reason. $script:AcceptedCollisions = @{ 'cat' = 'bat.json aliases cat -> bat. Deliberate: bat is a cat replacement.' 'ls' = 'eza.json aliases ls -> eza. Deliberate: eza is an ls replacement.' 'la' = 'eza.json aliases la -> eza. Not a coreutils utility itself; the installer synthesizes it while ls is enabled.' 'touch' = 'DFHelpers.FileSystem.ps1 aliases touch -> New-DFFile.' 'env' = 'DFHelpers.Environment.ps1 aliases env -> Get-DFEnv.' 'paste' = 'DFHelpers.Clipboard.ps1 aliases paste -> Get-DFFromClipboard.' } # Every command name DotForge creates, from the two places it creates them: # the manifest's AliasesToExport (helper aliases, created at import with # -Scope Global, so the module never owns them and ExportedAliases is empty), # and the tool database (tool aliases + picker aliases). $script:OwnedNames = [System.Collections.Generic.List[string]]::new() $manifestData = Import-PowerShellDataFile "$PSScriptRoot/../DotForge.psd1" if ($manifestData.AliasesToExport) { $script:OwnedNames.AddRange([string[]]@($manifestData.AliasesToExport)) } $db = Import-DFToolDb -ToolsPath "$PSScriptRoot/../Tools" -Force foreach ($tool in $db.Values) { $aliases = $tool.PSObject.Properties['aliases']?.Value if ($aliases) { $script:OwnedNames.AddRange([string[]]@($aliases.PSObject.Properties.Name)) } $picker = $tool.PSObject.Properties['picker']?.Value if ($picker -is [PSCustomObject]) { $pAlias = $picker.PSObject.Properties['alias']?.Value if ($pAlias) { $script:OwnedNames.Add([string]$pAlias) } } } $script:OwnedNames = @($script:OwnedNames | Sort-Object -Unique) } Describe 'Coreutils collision tripwire' { It 'flags any DotForge command that collides with coreutils and is not an accepted decision' { # Why this test exists: the runtime check (Get-DFCommandConflict) only fires on # machines that actually have coreutils. A contributor without it can add an # alias named `sort` or `stat` and never notice they have shipped a command that # silently cannot run for coreutils users -- the coreutils readline hook rewrites # the name before PowerShell resolves it, and Get-Command still reports # DotForge's version, so nothing looks wrong locally. $unexpected = $script:OwnedNames | Where-Object { $script:Coreutils -contains $_ } | Where-Object { -not $script:AcceptedCollisions.ContainsKey($_) } $unexpected | Should -BeNullOrEmpty -Because @" these DotForge commands collide with a coreutils utility of the same name: $($unexpected -join ', '). Coreutils' readline hook rewrites the name before PowerShell resolves it, so on a machine where that utility is enabled the DotForge command never runs -- and Get-Command still reports DotForge's version, so it looks fine while failing. Either rename the command, or accept the collision by adding it to `$script:AcceptedCollisions in this file with the reason. Users are warned at runtime by Get-DFCommandConflict. "@ } It 'keeps the accepted-collision list honest: every entry still collides' { # If coreutils drops a utility, or we rename an alias, the entry is dead weight # and should go -- otherwise the list slowly stops describing reality. foreach ($name in $script:AcceptedCollisions.Keys) { # 'la' is the documented exception: it is not a utility, it is synthesized # into the hook by the installer while 'ls' is enabled. if ($name -eq 'la') { continue } $script:Coreutils | Should -Contain $name -Because "'$name' is listed as an accepted coreutils collision but coreutils no longer ships it" } } It 'keeps the accepted-collision list honest: every entry is still a DotForge command' { foreach ($name in $script:AcceptedCollisions.Keys) { $script:OwnedNames | Should -Contain $name -Because "'$name' is listed as an accepted coreutils collision but DotForge no longer creates it" } } It 'gives a reason for every accepted collision' { foreach ($name in $script:AcceptedCollisions.Keys) { $script:AcceptedCollisions[$name] | Should -Not -BeNullOrEmpty } } It "does not list 'la' as a coreutils utility" { # Guards the fixture itself: coreutils-manager rejects `disable la`, so if this # ever appears in the list, Get-DFCommandConflict's la -> ls mapping needs review. $script:Coreutils | Should -Not -Contain 'la' } } |