psmux 3.3.4

Terminal multiplexer for Windows - tmux alternative for PowerShell and Windows Terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
# test_warm_off.ps1 - Comprehensive end-to-end tests for warm pane control
#
# Validates warm pane/server behavior across ALL creation paths:
# - Warm OFF: new-session, new-window, split-window (h+v), chained sessions
# - Warm ON: new-session, new-window, split-window (h+v), second session
# - Default (warm on): port files + show-options
# - Env var: PSMUX_NO_WARM=1
# - Runtime toggle: on -> off -> on

$ErrorActionPreference = "Stop"
$PSMUX_DIR = "$env:USERPROFILE\.psmux"

$pass = 0
$fail = 0
$total = 0

function Assert-True($condition, $msg) {
    $script:total++
    if ($condition) {
        Write-Host "  [PASS] $msg" -ForegroundColor Green
        $script:pass++
    } else {
        Write-Host "  [FAIL] $msg" -ForegroundColor Red
        $script:fail++
    }
}

function Kill-AllPsmux {
    Get-Process -Name psmux,tmux,pmux -ErrorAction SilentlyContinue |
        Stop-Process -Force -ErrorAction SilentlyContinue
    Start-Sleep -Milliseconds 500
    # Clean stale port files
    Get-ChildItem "$PSMUX_DIR\*.port" -ErrorAction SilentlyContinue |
        Remove-Item -Force -ErrorAction SilentlyContinue
    Get-ChildItem "$PSMUX_DIR\*.key" -ErrorAction SilentlyContinue |
        Remove-Item -Force -ErrorAction SilentlyContinue
}

function Get-WarmPortFiles {
    Get-ChildItem "$PSMUX_DIR\__warm__*.port" -ErrorAction SilentlyContinue
}

function Get-WarmProcesses {
    # Look for psmux processes whose command line contains __warm__
    Get-CimInstance Win32_Process -Filter "Name='psmux.exe'" -ErrorAction SilentlyContinue |
        Where-Object { $_.CommandLine -match '__warm__' }
}

# ── Setup ──────────────────────────────────────────────────────

Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Warm Control: Comprehensive E2E Tests" -ForegroundColor Cyan
Write-Host "============================================" -ForegroundColor Cyan
Write-Host ""

# Clean config and kill everything
Kill-AllPsmux

$configPath = "$env:USERPROFILE\.psmux.conf"
$hadConfig = Test-Path $configPath
if ($hadConfig) {
    $originalConfig = Get-Content $configPath -Raw
}

# Helper: set config for warm-off testing (preserves user lines + adds warm off)
function Set-WarmOff {
    Set-Content $configPath "set -g warm off"
}

# Helper: ensure no warm config (warm defaults to on)
function Set-WarmDefault {
    if ($hadConfig) {
        # Restore original but strip any warm line to test default behavior
        $cleaned = ($originalConfig -split "`n" | Where-Object { $_ -notmatch '^\s*set\s.*\bwarm\b' }) -join "`n"
        Set-Content $configPath $cleaned
    } else {
        Remove-Item $configPath -Force -ErrorAction SilentlyContinue
    }
}

# ══════════════════════════════════════════════════════════════
# TEST SUITE 1: Config-based warm off (set -g warm off)
# ══════════════════════════════════════════════════════════════
Write-Host "--- Suite 1: Config-based warm off ---" -ForegroundColor Yellow

# Write config
Set-WarmOff

# ── Test 1.1: New session should NOT spawn warm server ──
Write-Host ""
Write-Host "Test 1.1: New session with warm off" -ForegroundColor White
psmux new-session -d -s cfgtest1
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files after new-session"

$warmProcs = Get-WarmProcesses
Assert-True ($null -eq $warmProcs -or @($warmProcs).Count -eq 0) "No __warm__ processes after new-session"

# ── Test 1.2: New window should NOT spawn warm pane ──
Write-Host ""
Write-Host "Test 1.2: New window with warm off" -ForegroundColor White
psmux new-window -t cfgtest1
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files after new-window"

$warmProcs = Get-WarmProcesses
Assert-True ($null -eq $warmProcs -or @($warmProcs).Count -eq 0) "No __warm__ processes after new-window"

# ── Test 1.3: Vertical split should NOT spawn warm pane ──
Write-Host ""
Write-Host "Test 1.3: Vertical split with warm off" -ForegroundColor White
psmux split-window -v -t cfgtest1
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files after split-window -v"

# ── Test 1.4: Horizontal split should NOT spawn warm pane ──
Write-Host ""
Write-Host "Test 1.4: Horizontal split with warm off" -ForegroundColor White
psmux split-window -h -t cfgtest1
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files after split-window -h"

# ── Test 1.5: Second session should NOT spawn warm server ──
Write-Host ""
Write-Host "Test 1.5: Second session with warm off" -ForegroundColor White
psmux new-session -d -s cfgtest2
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files after second new-session"

$warmProcs = Get-WarmProcesses
Assert-True ($null -eq $warmProcs -or @($warmProcs).Count -eq 0) "No __warm__ processes after second new-session"

# ── Test 1.6: show-options confirms warm is off ──
Write-Host ""
Write-Host "Test 1.6: Show-options reports warm off" -ForegroundColor White
$warmVal = psmux show-options -g -v warm -t cfgtest1 2>&1
Assert-True ($warmVal -match "off") "show-options -g -v warm returns off"

# Cleanup suite 1
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux

# ══════════════════════════════════════════════════════════════
# TEST SUITE 2: Environment variable based warm off
# ══════════════════════════════════════════════════════════════
Write-Host ""
Write-Host "--- Suite 2: PSMUX_NO_WARM=1 env var ---" -ForegroundColor Yellow

# Clear config, use env var
Set-WarmDefault
$env:PSMUX_NO_WARM = "1"

# ── Test 2.1: New session with env var ──
Write-Host ""
Write-Host "Test 2.1: New session with PSMUX_NO_WARM=1" -ForegroundColor White
psmux new-session -d -s envtest1
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port files with PSMUX_NO_WARM=1"

$warmProcs = Get-WarmProcesses
Assert-True ($null -eq $warmProcs -or @($warmProcs).Count -eq 0) "No __warm__ processes with PSMUX_NO_WARM=1"

# ── Test 2.2: New window with env var ──
Write-Host ""
Write-Host "Test 2.2: New window with PSMUX_NO_WARM=1" -ForegroundColor White
psmux new-window -t envtest1
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port after new-window with env var"

# ── Test 2.3: Split with env var ──
Write-Host ""
Write-Host "Test 2.3: Split with PSMUX_NO_WARM=1" -ForegroundColor White
psmux split-window -h -t envtest1
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__.port after split with env var"

# Cleanup suite 2
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux
Remove-Item env:\PSMUX_NO_WARM -ErrorAction SilentlyContinue

# ══════════════════════════════════════════════════════════════
# TEST SUITE 3: Runtime commands (set-option -g warm off/on)
# Verifies actual warm file/process state after runtime toggles,
# not just show-options output.
# ══════════════════════════════════════════════════════════════
Write-Host ""
Write-Host "--- Suite 3: Runtime commands ---" -ForegroundColor Yellow

# No config override - ensure warm is enabled by default
Set-WarmDefault

# ── Test 3.1: Default (warm on) spawns warm server ──
Write-Host ""
Write-Host "Test 3.1: Default warm on spawns warm" -ForegroundColor White
psmux new-session -d -s toggletest
Start-Sleep -Seconds 5

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists with default (warm on)"

# ── Test 3.2: Runtime set warm off removes warm files ──
Write-Host ""
Write-Host "Test 3.2: Runtime warm off removes warm" -ForegroundColor White
psmux set-option -g warm off -t toggletest 2>$null
Start-Sleep -Seconds 3

$warmVal = psmux show-options -g -v warm -t toggletest 2>&1
Assert-True ($warmVal -match "off") "show-options reports warm off after runtime set"

# ── Test 3.3: New window after runtime warm off has no warm ──
Write-Host ""
Write-Host "Test 3.3: New window after runtime warm off" -ForegroundColor White
psmux new-window -t toggletest
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No warm port files after new-window (runtime warm off)"

# ── Test 3.4: Split after runtime warm off has no warm ──
Write-Host ""
Write-Host "Test 3.4: Split after runtime warm off" -ForegroundColor White
psmux split-window -v -t toggletest
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No warm port files after split-window (runtime warm off)"

# ── Test 3.5: Runtime set warm on restores warm ──
Write-Host ""
Write-Host "Test 3.5: Runtime warm on restores warm" -ForegroundColor White
psmux set-option -g warm on -t toggletest 2>$null
Start-Sleep -Seconds 3

$warmVal = psmux show-options -g -v warm -t toggletest 2>&1
Assert-True ($warmVal -match "on") "show-options reports warm on after runtime re-enable"

# ── Test 3.6: New window after runtime warm on has warm ──
Write-Host ""
Write-Host "Test 3.6: New window after runtime warm on" -ForegroundColor White
psmux new-window -t toggletest
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
# Warm pane is internal to the server, port file is for the warm SERVER
# After re-enabling warm, new operations should restore warm state
$warmVal2 = psmux show-options -g -v warm -t toggletest 2>&1
Assert-True ($warmVal2 -match "on") "warm still on after new-window (runtime warm on)"

# ── Test 3.7: Split after runtime warm on ──
Write-Host ""
Write-Host "Test 3.7: Split after runtime warm on" -ForegroundColor White
psmux split-window -h -t toggletest
Start-Sleep -Seconds 3

$warmVal3 = psmux show-options -g -v warm -t toggletest 2>&1
Assert-True ($warmVal3 -match "on") "warm still on after split-window (runtime warm on)"

# Cleanup suite 3
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux

# ══════════════════════════════════════════════════════════════
# TEST SUITE 4: Chained sessions (spooki44's scenario)
# ══════════════════════════════════════════════════════════════
Write-Host ""
Write-Host "--- Suite 4: Chained sessions (no warm inheritance) ---" -ForegroundColor Yellow

Set-WarmOff

Write-Host ""
Write-Host "Test 4.1: Create 3 sessions, no warm chain" -ForegroundColor White
psmux new-session -d -s chain1
Start-Sleep -Seconds 2
psmux new-session -d -s chain2
Start-Sleep -Seconds 2
psmux new-session -d -s chain3
Start-Sleep -Seconds 2

$warmFiles = Get-WarmPortFiles
Assert-True ($null -eq $warmFiles -or $warmFiles.Count -eq 0) "No __warm__ files after 3 chained sessions"

$warmProcs = Get-WarmProcesses
Assert-True ($null -eq $warmProcs -or @($warmProcs).Count -eq 0) "No __warm__ processes after 3 chained sessions"

# Every session should report warm off
foreach ($s in @("chain1", "chain2", "chain3")) {
    $v = psmux show-options -g -v warm -t $s 2>&1
    Assert-True ($v -match "off") "Session $s reports warm off"
}

# Cleanup suite 4
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux

# ══════════════════════════════════════════════════════════════
# TEST SUITE 5: Default behavior preserved (warm on)
# ══════════════════════════════════════════════════════════════
Write-Host ""
Write-Host "--- Suite 5: Default behavior preserved ---" -ForegroundColor Yellow

# Ensure warm is on by default (no warm config)
Set-WarmDefault

Write-Host ""
Write-Host "Test 5.1: Default config spawns warm server" -ForegroundColor White
psmux new-session -d -s defaulttest
Start-Sleep -Seconds 5

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists with default config"

$warmVal = psmux show-options -g -v warm -t defaulttest 2>&1
Assert-True ($warmVal -match "on") "show-options reports warm on by default"

# Cleanup suite 5
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux

# ══════════════════════════════════════════════════════════════
# TEST SUITE 6: Explicit warm on (set -g warm on)
# Verifies warm servers/panes are created for every path
# ══════════════════════════════════════════════════════════════
Write-Host ""
Write-Host "--- Suite 6: Explicit warm on (set -g warm on) ---" -ForegroundColor Yellow

Set-Content $configPath "set -g warm on"

# ── Test 6.1: New session with explicit warm on ──
Write-Host ""
Write-Host "Test 6.1: New session with explicit warm on" -ForegroundColor White
psmux new-session -d -s ontest1
Start-Sleep -Seconds 5

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists after new-session (warm on)"

$warmProcs = Get-WarmProcesses
Assert-True ($null -ne $warmProcs -and @($warmProcs).Count -gt 0) "Warm process exists after new-session (warm on)"

$warmVal = psmux show-options -g -v warm -t ontest1 2>&1
Assert-True ($warmVal -match "on") "show-options reports warm on (explicit)"

# ── Test 6.2: New window still has warm after ──
Write-Host ""
Write-Host "Test 6.2: New window with warm on" -ForegroundColor White
psmux new-window -t ontest1
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists after new-window (warm on)"

# ── Test 6.3: Vertical split still has warm after ──
Write-Host ""
Write-Host "Test 6.3: Vertical split with warm on" -ForegroundColor White
psmux split-window -v -t ontest1
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists after split-window -v (warm on)"

# ── Test 6.4: Horizontal split still has warm after ──
Write-Host ""
Write-Host "Test 6.4: Horizontal split with warm on" -ForegroundColor White
psmux split-window -h -t ontest1
Start-Sleep -Seconds 3

$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists after split-window -h (warm on)"

# ── Test 6.5: Second session also gets warm server ──
Write-Host ""
Write-Host "Test 6.5: Second session with warm on" -ForegroundColor White
psmux new-session -d -s ontest2
Start-Sleep -Seconds 5

# Should have at least one warm port file (possibly two, one per session)
$warmFiles = Get-WarmPortFiles
Assert-True ($null -ne $warmFiles -and @($warmFiles).Count -gt 0) "Warm port file exists after second new-session (warm on)"

# Cleanup suite 6
psmux kill-server 2>$null
Start-Sleep -Seconds 1
Kill-AllPsmux

# ── Restore original config ──
if ($hadConfig) {
    Set-Content $configPath $originalConfig
} else {
    Remove-Item $configPath -Force -ErrorAction SilentlyContinue
}

# ── Summary ──
Write-Host ""
Write-Host "============================================" -ForegroundColor Cyan
Write-Host " Results: $pass/$total passed, $fail failed" -ForegroundColor $(if ($fail -eq 0) { "Green" } else { "Red" })
Write-Host "============================================" -ForegroundColor Cyan

if ($fail -gt 0) { exit 1 }