spawn_placement_test.go RawHistoryFolder
1package core
2
3import (
4 "strings"
5 "testing"
6 "time"
7
8 "github.com/bnema/neferwl/internal/ports"
9)
10
11// A monitor can lose a named workspace while its slot is still configured.
12// The claim must remain pending, but its window follows ordinary placement.
13func TestSlotClaimWithoutWorkspace(t *testing.T) {
14 // A config message would remove both the workspace and its slot.
15 // Exercise the registry's missing-destination branch directly instead.
16 cfg := ports.Config{}
17 cfg.Keyboard.CmdKey = "alt"
18 cfg.Layout.MaxColumns = 1
19 c, err := New(cfg, Channels{Scenes: make(chan []ports.Scene, 1)}, Options{})
20 if err != nil {
21 t.Fatal(err)
22 }
23 key := slotKey{workspace: "gone", index: 1}
24 c.slots[key] = &slotState{argv: []string{"foot"}}
25 req := c.spawnSlot(key)
26 token := strings.TrimPrefix(req.Env[0], ports.SlotEnv+"=")
27 c.placement.place(c, ports.WindowMapped{ID: 21, Slot: token})
28 if !c.placement.slotPending(key) {
29 t.Fatal("unplaceable slot consumed its token")
30 }
31 if s, _ := c.screenOf(21); s == nil {
32 t.Fatal("window did not map normally")
33 }
34
35}
36
37func TestExpiredTerminalTokenMapsNormally(t *testing.T) {
38 cfg := ports.Config{}
39 cfg.Keyboard.CmdKey = "alt"
40 cfg.Layout.MaxColumns = 1
41 c, err := New(cfg, Channels{Scenes: make(chan []ports.Scene, 1)}, Options{})
42 if err != nil {
43 t.Fatal(err)
44 }
45 // Keep a different, focused workspace for the ordinary-window fallback.
46 c.cur().mon.AddWindow(1)
47 target := c.cur().mon.Current()
48 c.cur().mon.show(c.cur().mon.Workspaces[1])
49 focused := c.cur().mon.Current()
50 if focused == target {
51 t.Fatal("focus did not move to another workspace")
52 }
53 t0 := time.Unix(123, 0)
54 req := c.placement.request([]string{"foot"}, spawnTarget{kind: spawnTerminal, ws: target, at: t0})
55 token := strings.TrimPrefix(req.Env[0], ports.SlotEnv+"=")
56 c.placement.expireWorkspaceClaims(t0.Add(termRetry))
57 if _, ok := c.placement.pending[token]; !ok {
58 t.Fatal("claim expired at retry boundary")
59 }
60 c.placement.expireWorkspaceClaims(t0.Add(termRetry + time.Nanosecond))
61 if _, ok := c.placement.pending[token]; ok {
62 t.Fatal("claim survived past retry boundary")
63 }
64 c.placement.place(c, ports.WindowMapped{ID: 51, Slot: token})
65 if _, w := c.screenOf(51); w != focused || target.has(51) {
66 t.Fatal("expired token did not map onto focused workspace")
67 }
68}