psmux 3.3.4

Terminal multiplexer for Windows - tmux alternative for PowerShell and Windows Terminal
#!/usr/bin/env pwsh
# test_issue126_client_prefix.ps1 — Verify client_prefix flag updates when prefix key is pressed
# https://github.com/psmux/psmux/issues/126

$ErrorActionPreference = 'Continue'
$PSMUX = "$PSScriptRoot\..\target\release\psmux.exe"

$script:TestsPassed = 0
$script:TestsFailed = 0
function Write-Pass($msg) { Write-Host "  PASS: $msg" -ForegroundColor Green; $script:TestsPassed++ }
function Write-Fail($msg) { Write-Host "  FAIL: $msg" -ForegroundColor Red;   $script:TestsFailed++ }
function Write-Test($msg) { Write-Host "`n[$($script:TestsPassed + $script:TestsFailed + 1)] $msg" -ForegroundColor Cyan }

$SESSION = "prefix_flag_$(Get-Random)"

# Cleanup any leftover session
Start-Process -FilePath $PSMUX -ArgumentList "kill-session -t $SESSION" -WindowStyle Hidden -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1

# Create a detached session
Write-Host "`nCreating session '$SESSION'..." -ForegroundColor Yellow
Start-Process -FilePath $PSMUX -ArgumentList "new-session -s $SESSION -d" -WindowStyle Hidden
Start-Sleep -Seconds 3

$hasSession = & $PSMUX has-session -t $SESSION 2>&1
if ($LASTEXITCODE -ne 0) {
    Write-Host "ERROR: Cannot create session '$SESSION'" -ForegroundColor Red
    exit 1
}

function Psmux { & $PSMUX @args 2>&1; Start-Sleep -Milliseconds 300 }
function Fmt { param($f) (& $PSMUX display-message -t $SESSION -p "$f" 2>&1 | Out-String).Trim() }

# ---------------------------------------------------------------------------
# Test 1: client_prefix is 0 by default
# ---------------------------------------------------------------------------
Write-Test "client_prefix is 0 by default"
$val = Fmt '#{client_prefix}'
if ($val -eq "0") { Write-Pass "client_prefix = $val" }
else              { Write-Fail "Expected '0', got '$val'" }

# ---------------------------------------------------------------------------
# Test 2: conditional format shows 'NORM' when prefix not active
# ---------------------------------------------------------------------------
Write-Test "Conditional shows 'NORM' when prefix not active"
$val = Fmt '#{?client_prefix,PREFIX,NORM}'
if ($val -eq "NORM") { Write-Pass "conditional = $val" }
else                  { Write-Fail "Expected 'NORM', got '$val'" }

# ---------------------------------------------------------------------------
# Test 3: After prefix-begin, client_prefix is 1
# ---------------------------------------------------------------------------
Write-Test "client_prefix is 1 after prefix-begin"
# Send prefix-begin directly to set the flag on the server
$port = (Get-Content "$env:USERPROFILE\.psmux\$SESSION.port" -ErrorAction SilentlyContinue)
$key = (Get-Content "$env:USERPROFILE\.psmux\$SESSION.key" -ErrorAction SilentlyContinue)
if ($port -and $key) {
    # Send prefix-begin via raw TCP using PERSISTENT mode (like the real client does)
    try {
        $tcp = New-Object System.Net.Sockets.TcpClient("127.0.0.1", [int]$port)
        $stream = $tcp.GetStream()
        $stream.ReadTimeout = 5000
        $writer = New-Object System.IO.StreamWriter($stream)
        $reader = New-Object System.IO.StreamReader($stream)
        $writer.AutoFlush = $true
        $writer.WriteLine("AUTH $key")
        $auth_response = $reader.ReadLine()
        if ($auth_response -ne "OK") {
            Write-Fail "Auth failed: $auth_response"
            $tcp.Close()
            Psmux kill-session -t $SESSION | Out-Null
            exit 1
        }
        # Enter persistent mode so the connection stays alive for multiple commands
        $writer.WriteLine("PERSISTENT")
        Start-Sleep -Milliseconds 200

        $writer.WriteLine("prefix-begin")
        Start-Sleep -Milliseconds 300
        $val = Fmt '#{client_prefix}'
        if ($val -eq "1") { Write-Pass "client_prefix = $val" }
        else              { Write-Fail "Expected '1', got '$val'" }

        # -------------------------------------------------------------------
        # Test 4: conditional format shows 'PREFIX' when prefix active
        # -------------------------------------------------------------------
        Write-Test "Conditional shows 'PREFIX' when prefix active"
        $val = Fmt '#{?client_prefix,PREFIX,NORM}'
        if ($val -eq "PREFIX") { Write-Pass "conditional = $val" }
        else                    { Write-Fail "Expected 'PREFIX', got '$val'" }

        # -------------------------------------------------------------------
        # Test 5: client_key_table is 'prefix' when prefix active
        # -------------------------------------------------------------------
        Write-Test "client_key_table is 'prefix' when prefix active"
        $val = Fmt '#{client_key_table}'
        if ($val -eq "prefix") { Write-Pass "client_key_table = $val" }
        else                    { Write-Fail "Expected 'prefix', got '$val'" }

        # -------------------------------------------------------------------
        # Test 6: After prefix-end, client_prefix goes back to 0
        # -------------------------------------------------------------------
        Write-Test "client_prefix is 0 after prefix-end"
        $writer.WriteLine("prefix-end")
        Start-Sleep -Milliseconds 200
        $val = Fmt '#{client_prefix}'
        if ($val -eq "0") { Write-Pass "client_prefix = $val" }
        else              { Write-Fail "Expected '0', got '$val'" }

        # -------------------------------------------------------------------
        # Test 7: conditional reverts to 'NORM' after prefix-end
        # -------------------------------------------------------------------
        Write-Test "Conditional reverts to 'NORM' after prefix-end"
        $val = Fmt '#{?client_prefix,PREFIX,NORM}'
        if ($val -eq "NORM") { Write-Pass "conditional = $val" }
        else                  { Write-Fail "Expected 'NORM', got '$val'" }

        # -------------------------------------------------------------------
        # Test 8: client_key_table reverts to 'root' after prefix-end
        # -------------------------------------------------------------------
        Write-Test "client_key_table reverts to 'root' after prefix-end"
        $val = Fmt '#{client_key_table}'
        if ($val -eq "root") { Write-Pass "client_key_table = $val" }
        else                  { Write-Fail "Expected 'root', got '$val'" }

        # -------------------------------------------------------------------
        # Test 9: Rapid prefix toggle — correct on each
        # -------------------------------------------------------------------
        Write-Test "Rapid prefix toggle — flag flips correctly"
        $allCorrect = $true
        for ($i = 0; $i -lt 6; $i++) {
            if ($i % 2 -eq 0) { $writer.WriteLine("prefix-begin") }
            else               { $writer.WriteLine("prefix-end") }
            Start-Sleep -Milliseconds 150
            $val = Fmt '#{client_prefix}'
            $expected = if ($i % 2 -eq 0) { "1" } else { "0" }
            if ($val -ne $expected) {
                Write-Fail "Toggle $($i+1): expected '$expected', got '$val'"
                $allCorrect = $false
            }
        }
        if ($allCorrect) { Write-Pass "All 6 rapid toggles correct" }
        # Final cleanup: make sure prefix ends
        $writer.WriteLine("prefix-end")
        Start-Sleep -Milliseconds 100

        $tcp.Close()
    } catch {
        Write-Fail "TCP connection failed: $_"
    }
} else {
    Write-Fail "Cannot find session port/key files for direct protocol test"
}

# ---------------------------------------------------------------------------
# Cleanup
# ---------------------------------------------------------------------------
Psmux kill-session -t $SESSION | Out-Null
Write-Host "`n========================================" -ForegroundColor Yellow
Write-Host "Results: $($script:TestsPassed) passed, $($script:TestsFailed) failed" -ForegroundColor $(if ($script:TestsFailed -gt 0) { 'Red' } else { 'Green' })
exit $script:TestsFailed