# Issue #200 TRUE END TO END PROOF
# This test launches a REAL psmux session in a console window,
# sends ACTUAL KEYSTROKES (Ctrl+B, :, "new-session -d -s ...", Enter)
# and verifies the session was ACTUALLY created on disk.
#
# This is the DEFINITIVE proof that the command prompt code path works.
param(
[string]$SessionName = "e2e200_real",
[string]$TargetSession = "e2e200_target"
)
$ErrorActionPreference = "Stop"
$psmuxDir = "$env:USERPROFILE\.psmux"
# Cleanup from previous runs
Get-Process psmux -EA SilentlyContinue | Stop-Process -Force -EA SilentlyContinue
Start-Sleep -Seconds 1
Remove-Item "$psmuxDir\$SessionName.*" -Force -EA SilentlyContinue
Remove-Item "$psmuxDir\$TargetSession.*" -Force -EA SilentlyContinue
Add-Type @"
using System;
using System.Runtime.InteropServices;
public class Win32Input {
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
public const byte VK_CONTROL = 0x11;
public const byte VK_RETURN = 0x0D;
public const uint KEYEVENTF_KEYUP = 0x0002;
public static void SendCtrlB() {
keybd_event(VK_CONTROL, 0, 0, UIntPtr.Zero);
keybd_event(0x42, 0, 0, UIntPtr.Zero); // 'B'
keybd_event(0x42, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
}
public static void SendChar(char c) {
// Use SendInput for proper character input
byte vk = 0;
bool shift = false;
if (c >= 'a' && c <= 'z') vk = (byte)(0x41 + (c - 'a'));
else if (c >= 'A' && c <= 'Z') { vk = (byte)(0x41 + (c - 'A')); shift = true; }
else if (c >= '0' && c <= '9') vk = (byte)(0x30 + (c - '0'));
else if (c == '-') vk = 0xBD;
else if (c == '_') { vk = 0xBD; shift = true; }
else if (c == ' ') vk = 0x20;
else if (c == ':') { vk = 0xBA; shift = true; }
else if (c == '.') vk = 0xBE;
else if (c == '/') vk = 0xBF;
else if (c == '\\') vk = 0xDC;
else return;
if (shift) keybd_event(0x10, 0, 0, UIntPtr.Zero);
keybd_event(vk, 0, 0, UIntPtr.Zero);
keybd_event(vk, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
if (shift) keybd_event(0x10, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
}
public static void SendEnter() {
keybd_event(VK_RETURN, 0, 0, UIntPtr.Zero);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, UIntPtr.Zero);
}
public static void SendString(string s) {
foreach (char c in s) {
SendChar(c);
System.Threading.Thread.Sleep(30);
}
}
}
"@
Write-Host "=== Issue #200 TRUE END TO END PROOF ===" -ForegroundColor Cyan
Write-Host ""
# Step 1: Launch psmux in a new console window (ATTACHED session)
Write-Host "[1/5] Launching psmux in a new console window..." -ForegroundColor Yellow
$psmuxExe = (Get-Command psmux -EA Stop).Source
$proc = Start-Process -FilePath $psmuxExe -ArgumentList "new-session","-s",$SessionName -PassThru
Write-Host " PID: $($proc.Id)"
# Wait for session to be fully ready
$ready = $false
for ($i = 0; $i -lt 50; $i++) {
Start-Sleep -Milliseconds 200
if (Test-Path "$psmuxDir\$SessionName.port") {
$port = (Get-Content "$psmuxDir\$SessionName.port" -Raw).Trim()
try {
$tcp = [System.Net.Sockets.TcpClient]::new("127.0.0.1", [int]$port)
$tcp.Close()
$ready = $true
break
} catch {}
}
}
if (-not $ready) {
Write-Host " [FAIL] Session did not start in time" -ForegroundColor Red
exit 1
}
Write-Host " [OK] Session '$SessionName' is alive on port $port" -ForegroundColor Green
# Step 2: Find the console window and bring it to foreground
Write-Host "[2/5] Finding console window..." -ForegroundColor Yellow
Start-Sleep -Seconds 2 # Let the TUI fully render
# Try to find the window by process
$hwnd = $proc.MainWindowHandle
if ($hwnd -eq [IntPtr]::Zero) {
# Try enumerating
Start-Sleep -Seconds 1
$hwnd = $proc.MainWindowHandle
}
if ($hwnd -eq [IntPtr]::Zero) {
Write-Host " [WARN] Could not get window handle directly, trying FindWindow..." -ForegroundColor Yellow
# Fallback: use process window title
$proc.Refresh()
$title = $proc.MainWindowTitle
Write-Host " Window title: '$title'"
}
# Bring window to front
if ($hwnd -ne [IntPtr]::Zero) {
[Win32Input]::ShowWindow($hwnd, 9) | Out-Null # SW_RESTORE
[Win32Input]::SetForegroundWindow($hwnd) | Out-Null
Write-Host " [OK] Window focused (handle: $hwnd)" -ForegroundColor Green
} else {
Write-Host " [WARN] No window handle, will try anyway" -ForegroundColor Yellow
}
Start-Sleep -Milliseconds 500
# Step 3: Send Ctrl+B (prefix), then : to open command prompt
Write-Host "[3/5] Sending prefix (Ctrl+B) then ':' to open command prompt..." -ForegroundColor Yellow
[Win32Input]::SendCtrlB()
Start-Sleep -Milliseconds 300
[Win32Input]::SendChar(':')
Start-Sleep -Milliseconds 500
Write-Host " [OK] Command prompt should be open" -ForegroundColor Green
# Step 4: Type the new-session command and press Enter
$cmd = "new-session -d -s $TargetSession"
Write-Host "[4/5] Typing: '$cmd' and pressing Enter..." -ForegroundColor Yellow
[Win32Input]::SendString($cmd)
Start-Sleep -Milliseconds 300
[Win32Input]::SendEnter()
Write-Host " [OK] Command sent" -ForegroundColor Green
# Step 5: Wait and check if the session was created
Write-Host "[5/5] Waiting for session '$TargetSession' to appear..." -ForegroundColor Yellow
$created = $false
for ($i = 0; $i -lt 80; $i++) {
Start-Sleep -Milliseconds 250
if (Test-Path "$psmuxDir\$TargetSession.port") {
$tp = (Get-Content "$psmuxDir\$TargetSession.port" -Raw).Trim()
try {
$tcp2 = [System.Net.Sockets.TcpClient]::new("127.0.0.1", [int]$tp)
$tcp2.Close()
$created = $true
break
} catch {}
}
}
Write-Host ""
Write-Host "=========================================" -ForegroundColor Cyan
if ($created) {
Write-Host " PASS: Session '$TargetSession' was CREATED!" -ForegroundColor Green
Write-Host " Port file: $psmuxDir\$TargetSession.port" -ForegroundColor Green
Write-Host " Port: $tp" -ForegroundColor Green
Write-Host ""
Write-Host " This PROVES the command prompt (prefix+:) code path" -ForegroundColor Green
Write-Host " in execute_command_string_single() correctly spawns" -ForegroundColor Green
Write-Host " a new session. Issue #200 is FIXED." -ForegroundColor Green
} else {
Write-Host " FAIL: Session '$TargetSession' was NOT created!" -ForegroundColor Red
Write-Host " Port file not found at: $psmuxDir\$TargetSession.port" -ForegroundColor Red
Write-Host " The command prompt code path may still be broken." -ForegroundColor Red
}
Write-Host "=========================================" -ForegroundColor Cyan
# Cleanup
Write-Host "`nCleaning up..." -ForegroundColor Yellow
# Kill target session
if (Test-Path "$psmuxDir\$TargetSession.port") {
$tk = if (Test-Path "$psmuxDir\$TargetSession.key") { (Get-Content "$psmuxDir\$TargetSession.key" -Raw).Trim() } else { "" }
if ($tk -and $tp) {
try {
$tc = [System.Net.Sockets.TcpClient]::new("127.0.0.1", [int]$tp)
$s = $tc.GetStream(); $w = [System.IO.StreamWriter]::new($s)
$w.Write("AUTH $tk`n"); $w.Flush()
$w.Write("kill-server`n"); $w.Flush()
$tc.Close()
} catch {}
}
}
# Kill main session
if (Test-Path "$psmuxDir\$SessionName.port") {
$mk = if (Test-Path "$psmuxDir\$SessionName.key") { (Get-Content "$psmuxDir\$SessionName.key" -Raw).Trim() } else { "" }
if ($mk -and $port) {
try {
$tc2 = [System.Net.Sockets.TcpClient]::new("127.0.0.1", [int]$port)
$s2 = $tc2.GetStream(); $w2 = [System.IO.StreamWriter]::new($s2)
$w2.Write("AUTH $mk`n"); $w2.Flush()
$w2.Write("kill-server`n"); $w2.Flush()
$tc2.Close()
} catch {}
}
}
Start-Sleep -Seconds 1
Remove-Item "$psmuxDir\$SessionName.*" -Force -EA SilentlyContinue
Remove-Item "$psmuxDir\$TargetSession.*" -Force -EA SilentlyContinue
if ($created) { exit 0 } else { exit 1 }