Repository navigation
Expand file tree
/
Copy pathdriver_test.go
More file actions
705 lines (628 loc) · 28 KB
/
Copy pathdriver_test.go
File metadata and controls
705 lines (628 loc) · 28 KB
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
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
package remote
// driver_test.go is the room's one keyboard, proven on the wire.
//
// Every question here is a question about WHO MAY TYPE, so every one of them is
// asked with at least two connections onto one [Session] — which is the shape a
// host serves and the shape driver.go exists for. The frames are the real
// frames and the sentences are the real sentences: a test that asserted a
// paraphrase of the refusal would pass on the day somebody rewrote it into
// machinery.
import (
"io"
"strings"
"sync/atomic"
"testing"
"time"
"github.com/Agent-Field/codeaf/internal/session"
)
// driverOf is the "driver" frame a link is waiting for. A hand-over is fanned
// out to everybody in the room, so this is what an OLDER window sees the moment
// a newer one arrives.
func driverOf(l *link) Driver {
l.t.Helper()
frame := l.await(func(f Frame) bool { return f.Kind == "driver" })
return decode[Driver](l.t, frame.Payload)
}
// driverSaying is the note that says the keyboard is on `machine`, past any note
// about a moment that has already passed.
//
// A WINDOW CAN BE TOLD IT DRIVES AFTER IT HAS STOPPED DRIVING, and that is the
// engine's own ordering rather than a fault. The room is told who drives AFTER
// the arriving window's welcome has been written — [server.attached] says why it
// cannot be before, and it is that connection's own writer — so a SECOND window
// that arrives in that gap is told it holds the keyboard by the FIRST window's
// announcement. The note is true about the instant it names and is corrected by
// the next frame, and per-connection ordering keeps the correction behind it.
//
// So a test that read "the next driver frame" was reading a coin flip: about one
// run in twenty alone, and reliably at -count=400. It is what failed `touched
// packages` on both #910 and #914 on 2026-09-11. What these tests are about is
// where the keyboard ENDED UP, so that is what they wait for.
func driverSaying(l *link, machine string) Driver {
l.t.Helper()
for {
frame := l.await(func(f Frame) bool { return f.Kind == "driver" })
note := decode[Driver](l.t, frame.Payload)
if note.Machine == machine {
return note
}
if !note.Yours {
l.t.Fatalf("the keyboard was said to be on %q, want %q", note.Machine, machine)
}
}
}
// ── who drives ──────────────────────────────────────────────────────────────
// The first window in an empty room has the keyboard, and nobody has to ask.
func TestTheFirstWindowInTheRoomHasTheKeyboard(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
only := dialSession(t, sess)
welcome := decode[Welcome](t, only.hello(Hello{Version: Version, Surface: "macbook"}).Payload)
if !welcome.Driver.Yours {
t.Fatalf("the only window in the room was not given the keyboard: %+v", welcome.Driver)
}
if result := only.call(1, MethodSubmit, SubmitArgs{Text: "go"}); result.Error != "" {
t.Fatalf("the only window could not type: %s", result.Error)
}
}
// THE NEWEST WINDOW DRIVES. A person who walked to another machine and opened
// the conversation there is not an intruder to be refused — they are simply
// where the person now is.
func TestTheNewestWindowTakesTheKeyboardAndTheOlderOneIsTold(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
welcome := decode[Welcome](t, away.hello(Hello{Version: Version, Surface: "tower"}).Payload)
if !welcome.Driver.Yours {
t.Fatalf("the window that just arrived was not given the keyboard: %+v", welcome.Driver)
}
// And the window it arrived in front of is TOLD, on a frame of its own, so
// that its screen stops offering a composer this same instant.
told := driverOf(desk)
if told.Yours {
t.Fatalf("the older window still believed it was driving")
}
if told.Machine != "tower" {
t.Fatalf("the older window was told the keyboard is on %q, want tower", told.Machine)
}
if told.Here {
t.Fatalf("a window on another machine was reported as one on this one")
}
}
// Two windows on ONE machine send one name, and that is how the engine can tell
// the desk across the room from the terminal behind this one. `another window`
// is the word codeaf already uses at home for exactly this.
func TestASecondWindowOnTheSameMachineReadsAsAnotherWindow(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
first := dialSession(t, sess)
first.hello(Hello{Version: Version, Surface: "macbook"})
second := dialSession(t, sess)
second.hello(Hello{Version: Version, Surface: "macbook"})
told := driverOf(first)
if !told.Here {
t.Fatalf("a second window on the same machine was not reported as one: %+v", told)
}
if refused := notDrivingWord(told); !strings.Contains(refused, "in another window") {
t.Fatalf("the refusal named a machine where it should have said another window: %q", refused)
}
}
// ── the refusal ─────────────────────────────────────────────────────────────
// A MESSAGE A PERSON PRESSED ENTER ON EITHER LANDS OR IS ANSWERED. The third
// outcome — it disappears because a window somewhere else had the keyboard — is
// the one nobody could debug from the screen.
func TestAWindowWithoutTheKeyboardIsRefusedInWordsAndNotInSilence(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
for _, door := range []struct {
method string
payload any
}{
{MethodSubmit, SubmitArgs{Text: "go"}},
{MethodSubmitBash, SubmitArgs{Text: "!pwd"}},
{MethodFollowUp, SubmitArgs{Text: "and also"}},
{MethodSteer, SubmitArgs{Text: "use the other file"}},
{MethodSubmitImage, SubmitImageArgs{Text: "look"}},
{MethodSubmitFiles, SubmitFilesArgs{Text: "here"}},
} {
result := desk.call(1, door.method, door.payload)
want := "the keyboard is on tower right now — press enter here to move it here"
if result.Error != want {
t.Fatalf("%s from a watcher answered %q, want %q", door.method, result.Error, want)
}
}
// And nothing else is closed to it. A watcher is a person watching their own
// work, not a guest: it reads the transcript, answers cards and interrupts.
away.ok(9, MethodSubmit, SubmitArgs{Text: "go"})
desk.ok(2, MethodTranscript, nil)
desk.ok(3, MethodInterrupt, nil)
}
// ── taking it back ──────────────────────────────────────────────────────────
// One round trip and never a reconnect: the connection under a take-back never
// moved, and the window that had it is told in the same breath.
func TestTakingTheKeyboardBackMovesItAndTellsTheOtherWindow(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
if told := driverOf(desk); told.Yours {
t.Fatalf("the desk was not made a watcher to begin with")
}
desk.ok(1, MethodTake, nil)
// The taker can type again...
desk.ok(2, MethodSubmit, SubmitArgs{Text: "go"})
// ...and the window that had it is now the watcher, told by a frame rather
// than by discovering it on its next keystroke.
told := driverSaying(away, "macbook")
if told.Yours {
t.Fatalf("both windows believe they hold the keyboard")
}
if result := away.call(3, MethodSubmit, SubmitArgs{Text: "no"}); result.Error == "" {
t.Fatalf("the new watcher was allowed to type")
}
}
// M11: the newly taken keyboard can steer, every watcher receives the steer
// lifecycle, and no watcher is told that those words opened a fresh turn.
func TestTheDriverCanSteerWithoutBroadcastingAFreshTurn(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
driverOf(desk)
desk.ok(1, MethodTake, nil)
driverOf(away)
ref := decode[StreamRef](t, desk.ok(2, MethodSteer, SubmitArgs{Text: "use staging"}).Payload)
if len(agent.steered) != 1 || agent.steered[0] != "use staging" {
t.Fatalf("the newly taken keyboard steered %q", agent.steered)
}
stream := agent.stream(0)
stream <- session.Event{Kind: session.EventSteerAccepted, Steer: &session.SteerNote{ID: 7, Words: "use staging"}}
stream <- session.Event{Kind: session.EventSteerConsumed, Steer: &session.SteerNote{ID: 7, Words: "use staging"}}
close(stream)
var kinds []session.EventKind
for len(kinds) < 2 {
frame := away.await(func(frame Frame) bool { return frame.Kind == "event" && frame.ID == ref.Stream })
kinds = append(kinds, decode[EventWire](t, frame.Payload).Unwire().Kind)
}
if kinds[0] != session.EventSteerAccepted || kinds[1] != session.EventSteerConsumed {
t.Fatalf("the watcher received steer events %v", kinds)
}
frames := append([]Frame(nil), away.spare...)
frames = append(frames, drain(away)...)
for _, frame := range frames {
if frame.Kind == "turn" {
t.Fatal("the steer was broadcast to the watcher as a fresh turn")
}
}
}
// ── leaving ─────────────────────────────────────────────────────────────────
// The keyboard is never left on a window that has gone, so the last window
// standing can always type. A FORGOTTEN WINDOW STILL SHOWING THE WORK IS A
// FEATURE — this is what happens when somebody finally closes it.
func TestClosingTheDrivingWindowHandsTheKeyboardOnToTheNewestLeft(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
driverOf(desk)
if err := away.end(); err != nil {
t.Fatalf("the driving window ended with %v", err)
}
if told := driverOf(desk); !told.Yours {
t.Fatalf("the window left behind was not handed the keyboard: %+v", told)
}
desk.ok(1, MethodSubmit, SubmitArgs{Text: "go"})
}
// A REDIAL IS AN ATTACH THE PERSON DID NOT MAKE. The lid they closed in one city
// reconnecting half an hour later must not pull the keyboard off the machine
// they are sitting at — which is what [Hello.Back] is for.
func TestALinkComingBackDoesNotStealTheKeyboardFromWhereThePersonWent(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
driverOf(desk)
// The desk's link dies and comes back, saying it has been here before.
if err := desk.end(); err != nil {
t.Fatalf("the desk's link ended with %v", err)
}
back := dialSession(t, sess)
welcome := decode[Welcome](t, back.hello(Hello{Version: Version, Surface: "macbook", Back: true}).Payload)
if welcome.Driver.Yours {
t.Fatalf("a link coming back took the keyboard off the machine the person walked to")
}
if welcome.Driver.Machine != "tower" {
t.Fatalf("the returning window was told the keyboard is on %q, want tower", welcome.Driver.Machine)
}
// And a returning link that finds the keyboard going spare does take it,
// because there is nobody to take it from.
if err := away.end(); err != nil {
t.Fatalf("the far window ended with %v", err)
}
if told := driverOf(back); !told.Yours {
t.Fatalf("the last window standing was left unable to type: %+v", told)
}
}
// A WATCHER NEVER TAKES THE KEYBOARD, AND `Back` WAS NOT ENOUGH.
//
// A surface opened to READ one task of a conversation running next door
// ([Hello.Watch]) must not end up driving it. `Back` gets the first half right
// and the second half exactly wrong: a returning surface takes the keyboard the
// moment it is going spare, and going spare is the ordinary state of a
// conversation whose window has stepped away for a second. So the reader is
// refused it on arrival, refused it when the driver leaves, refused it through
// [MethodTake], and refused when it types anyway — in words about itself, because
// nothing about the conversation is in the way.
func TestAWatchingSurfaceIsNeverGivenTheKeyboardEvenWhenItIsGoingSpare(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
// The reader arrives NEWEST, which is what would ordinarily take the keyboard.
reader := dialSession(t, sess)
welcome := decode[Welcome](t, reader.hello(Hello{Version: Version, Surface: "macbook", Watch: true}).Payload)
if welcome.Driver.Yours {
t.Fatal("a reading surface was handed the keyboard on arrival")
}
if told := driverOf(desk); !told.Yours {
t.Fatalf("a reading surface took the keyboard off the window that owns the work: %+v", told)
}
// The window that owns the work goes away. There is nobody left who may type,
// and the room is left with NO driver rather than with the reader.
if err := desk.end(); err != nil {
t.Fatalf("the desk's link ended with %v", err)
}
if told := driverOf(reader); told.Yours {
t.Fatalf("a reading surface inherited a keyboard nobody was holding: %+v", told)
}
// ...AND ASKING FOR IT OUTRIGHT IS REFUSED IN WORDS RATHER THAN ANSWERED WITH
// A DRIVER. [MethodTake] is not on the reader's allow-list, so the refusal
// lands one layer ABOVE the hand-over rule — the call never reaches
// [Session.take] at all — and the result carries a sentence instead of a
// [Driver]. That is the stronger of the two guarantees and it is the one the
// wire actually gives, so it is what is demanded here: a test that decoded a
// Driver out of this frame would be reading an empty payload and calling the
// zero value a pass.
took := reader.call(1, MethodTake, nil)
if took.Error == "" {
t.Fatalf("a reading surface was allowed to ask for the keyboard: %+v", took)
}
if !strings.Contains(took.Error, watchingWord) {
t.Fatalf("the refusal is %q, want the reader's own words %q", took.Error, watchingWord)
}
if !strings.Contains(took.Error, MethodTake) {
t.Fatalf("the refusal does not name the door that was tried: %q", took.Error)
}
if len(took.Payload) != 0 {
t.Fatalf("a refused take still answered with a driver: %s", took.Payload)
}
}
// AN OLD ENGINE IS REFUSED AT THE DOOR RATHER THAN TRUSTED WITH THE FLAGS.
//
// [Hello.Join] and [Hello.Watch] are omitempty booleans, which is precisely what
// an older build DISCARDS in silence — and a build that discarded them would boot
// a conversation to answer a question about running work, and hand this reader
// the keyboard, before any welcome existed to check. The version gate is what
// stops it, it runs before `Open` and before `attach`, and this is the test that
// the gate is in front of both.
func TestAJoinOrWatchHelloFromAnotherProtocolIsRefusedBeforeAnythingOpens(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
var opened atomic.Int64
old := dialOpening(t, func(Hello) (*Session, error) { opened.Add(1); return sess, nil })
frame := old.hello(Hello{Version: Version - 1, Surface: "reader", Join: true, Watch: true})
if frame.Kind != "fatal" {
t.Fatalf("a hello from another protocol was answered with %q, want a refusal", frame.Kind)
}
if !strings.Contains(frame.Error, "matching versions") {
t.Fatalf("the refusal does not say what was wrong with the hello: %q", frame.Error)
}
if got := opened.Load(); got != 0 {
t.Fatalf("a refused hello reached the conversation door %d times", got)
}
// AND NOTHING ABOUT THE OWNER MOVED, WHICH IS PROVEN BY A SILENCE AND A CALL.
//
// THE SILENCE IS THE POINT AND IT CANNOT BE AWAITED. A hand-over is what
// produces a `driver` frame, and the whole claim here is that no hand-over
// happened — so waiting for one is waiting for the thing whose absence is the
// pass, and it can only ever time out. What is asked instead is the fact that
// frame would have carried: the desk can still type, which is what holding the
// keyboard MEANS on this wire, and it is answered rather than awaited.
desk.ok(1, MethodSubmit, SubmitArgs{Text: "go"})
// AND THE REFUSED CONNECTION IS OVER, on its own side, having opened nothing.
if err := old.end(); err == nil {
t.Fatal("a refused hello left the engine serving that connection")
}
}
// A WATCHER CHANGES NOTHING, EVEN THROUGH A DOOR THAT NEVER TYPES.
//
// The driver rule covers the methods that put WORDS into a conversation, which is
// not the same set as the methods that change one: a model, an effort rung, a
// permission, a resolve, a revive, opening another session in this one, closing
// it. Every one of those was open to a reader before [Hello.Watch], and every one
// of them acts on somebody else's work. The guard is an ALLOW-LIST, so this test
// asks for things a reader has no business asking for and expects a refusal in
// its own words rather than a change.
func TestAWatchingSurfaceIsRefusedEveryDoorThatChangesAnything(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
reader := dialSession(t, sess)
reader.hello(Hello{Version: Version, Surface: "reader", Watch: true})
was := agent.model
for id, call := range []struct {
method string
payload any
}{
{MethodSetModel, "someone/else"},
{MethodSubmit, "go"},
{MethodSubmitBash, SubmitArgs{Text: "!pwd"}},
{MethodInterrupt, nil},
{MethodSessionNew, nil},
{MethodTaskStop, TaskStopArgs{ID: "7"}},
} {
frame := reader.call(uint64(id+1), call.method, call.payload)
if frame.Error == "" {
t.Fatalf("%s was allowed on a reading surface", call.method)
}
if !strings.Contains(frame.Error, watchingWord) {
t.Fatalf("%s was refused with %q, want the reader's own sentence", call.method, frame.Error)
}
}
if agent.model != was {
t.Fatalf("a reading surface moved the model to %q", agent.model)
}
// AND THE ONE DOOR IT EXISTS FOR IS OPEN. A guard that refused this too would
// be a connection with nothing to do.
if frame := reader.call(90, MethodTaskRoom, TaskRoomArgs{ID: 7, Tail: 4}); frame.Error != "" &&
strings.Contains(frame.Error, watchingWord) {
t.Fatalf("the reader was refused the one thing it is for: %v", frame.Error)
}
// The window that owns the work still drives and is untouched.
if told := driverOf(desk); !told.Yours {
t.Fatalf("the reader took the keyboard: %+v", told)
}
}
// A READING SURFACE MAY READ ONE TASK'S STORED PAGE AND NONE OF ITS VERBS. A
// program's task writes no worker journal, so the page another window opens
// onto it reads the task's page in the owner's store instead
// (internal/tui3's taskowner.go). The page's verbs — a note, a pause, a stop —
// act on the owner's work and stay refused. And the read is bound to the
// conversation the reader joined, as the journal is: once the owner opens
// something else, it is told rather than handed the replacement's task.
func TestAReadingSurfaceReadsAProgramsPageAndNoneOfItsVerbs(t *testing.T) {
first := &fakeAgent{model: "a/b", title: "the one being read"}
second := &fakeAgent{model: "a/b", title: "something else"}
engine := engineOn(first)
engine.Fresh = func() (WrappedAgent, string, error) { return second, "/sessions/two.jsonl", nil }
sess := NewSession(engine, true)
owner := dialSession(t, sess)
owner.hello(Hello{Version: Version, Surface: "macbook"})
reader := dialSession(t, sess)
reader.hello(Hello{
Version: Version, Surface: "reader",
Session: engine.SessionFile, Join: true, Watch: true,
})
if frame := reader.call(1, MethodPlanTaskPage, PlanTaskPageArgs{ID: "7"}); frame.Error != "" {
t.Fatalf("the reader was refused a program's page: %v", frame.Error)
}
for id, call := range []struct {
method string
payload any
}{
{MethodPlanNote, PlanTextArgs{ID: "7", Text: "go faster"}},
{MethodPlanPause, PlanTaskArgs{ID: "7"}},
{MethodPlanCancel, PlanTaskArgs{ID: "7"}},
} {
frame := reader.call(uint64(id+10), call.method, call.payload)
if !strings.Contains(frame.Error, watchingWord) {
t.Fatalf("%s on a reading surface answered %q, want the reader's own refusal", call.method, frame.Error)
}
}
if len(first.planSteers) != 0 {
t.Fatalf("a reading surface acted on the owner's work: %v", first.planSteers)
}
owner.ok(20, MethodSessionNew, nil)
frame := reader.call(21, MethodPlanTaskPage, PlanTaskPageArgs{ID: "7"})
if !strings.Contains(frame.Error, "not open here any more") {
t.Fatalf("after the owner opened something else the reader's page read answered %q, want the sentence its page acts on", frame.Error)
}
}
// ── the client half ─────────────────────────────────────────────────────────
// The real client against the real engine over an in-memory pipe: what a
// surface actually holds, and what it is woken by.
func TestTheSurfaceLearnsItHasBecomeAWatcherWithNobodyTouchingIt(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
first, err := loopSession(sess, Hello{Surface: "macbook"})
if err != nil {
t.Fatalf("dial: %v", err)
}
defer first.Close()
if !first.Client.Driver().Yours {
t.Fatalf("the first surface did not hold the keyboard")
}
// The wake is taken BEFORE the second surface arrives, which is the whole
// point of it: nothing happens on this machine, and this surface still has
// to stop drawing a composer.
woken := first.Client.DriverChanged()
second, err := loopSession(sess, Hello{Surface: "tower"})
if err != nil {
t.Fatalf("second dial: %v", err)
}
defer second.Close()
select {
case <-woken:
case <-time.After(5 * time.Second):
t.Fatalf("the surface was never woken when the keyboard moved")
}
driver := first.Client.Driver()
if driver.Yours || driver.Machine != "tower" {
t.Fatalf("the watching surface holds %+v", driver)
}
// Typing at it is refused in the engine's own words, and the words name the
// way back.
if _, err := first.Client.Agent().Submit(t.Context(), "go"); err == nil {
t.Fatalf("the watching surface was allowed to type")
} else if !strings.Contains(err.Error(), "press enter here to move it here") {
t.Fatalf("the refusal did not say how to get back: %v", err)
}
// And taking it back is one call on the connection that was already open.
if err := first.Client.Take(); err != nil {
t.Fatalf("take: %v", err)
}
if !first.Client.Driver().Yours {
t.Fatalf("the surface that took the keyboard does not believe it has it")
}
if _, err := first.Client.Agent().Submit(t.Context(), "go"); err != nil {
t.Fatalf("the surface that took the keyboard could not type: %v", err)
}
agent.finish(agent.stream(0))
}
// loopSession is [Loopback] onto a conversation that already exists — the same
// difference [dialSession] is to [dial], and for the same reason.
func loopSession(sess *Session, hello Hello) (*Loop, error) {
return loopOver(hello, func(engine io.ReadWriteCloser) error {
return ServeAttach(engine, engine, AttachOptions{
Open: func(Hello) (*Session, error) { return sess, nil },
})
})
}
// ── the name on the wire ────────────────────────────────────────────────────
// A BOUNDARY THAT TRUSTS ITS INPUT IS NOT A BOUNDARY. This string arrives from
// another machine and ends up in a line on somebody's screen, so an escape
// sequence in it would be an escape sequence in their terminal.
func TestAMachineNameFromTheWireIsMadeSafeToDraw(t *testing.T) {
for _, probe := range []struct{ said, want string }{
{"tower", "tower"},
{" tower ", "tower"},
{"spa\x1b[2Jrk", "spa[2Jrk"},
{"tower\nmacbook", "towermacbook"},
{strings.Repeat("x", 200), strings.Repeat("x", machineNameMost)},
{"", ""},
} {
if got := machineLabel(probe.said); got != probe.want {
t.Errorf("machineLabel(%q) = %q, want %q", probe.said, got, probe.want)
}
}
}
// A machine with no name of its own says nothing about one, and the sentence
// falls back to the word that is true either way.
func TestAWindowWithNoNameIsStillAnotherWindow(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
first := dialSession(t, sess)
first.hello(Hello{Version: Version})
second := dialSession(t, sess)
second.hello(Hello{Version: Version})
told := driverOf(first)
if !told.Here || told.Machine != "" {
t.Fatalf("a nameless window was drawn as something: %+v", told)
}
want := "the keyboard is in another window right now — press enter here to move it here"
if got := notDrivingWord(told); got != want {
t.Fatalf("the refusal reads %q, want %q", got, want)
}
}
// A turn's events still reach a watcher, which is the whole reason the older
// windows stay attached rather than being closed: a forgotten window still
// showing the work is a feature.
func TestAWatcherKeepsReceivingTheTurnItCannotStart(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
desk := dialSession(t, sess)
desk.hello(Hello{Version: Version, Surface: "macbook"})
away := dialSession(t, sess)
away.hello(Hello{Version: Version, Surface: "tower"})
driverOf(desk)
ref := decode[StreamRef](t, away.ok(1, MethodSubmit, SubmitArgs{Text: "go"}).Payload)
// THE WATCHER IS TOLD THE TURN STARTED, BEFORE ITS FIRST EVENT. A surface
// only draws a stream it knows about, so without this the events below go
// past a watching window in silence — the whole promise of staying attached,
// unkept ([Turn]).
told := decode[Turn](t, desk.await(func(f Frame) bool { return f.Kind == "turn" }).Payload)
if told.Stream != ref.Stream {
t.Fatalf("the watcher was told about stream %d, want %d", told.Stream, ref.Stream)
}
if told.Said != "go" {
t.Fatalf("the watcher was told the turn opened on %q — a reply with no question above it", told.Said)
}
stream := agent.stream(0)
stream <- session.Event{Kind: session.EventTextDelta, Text: "hello"}
frame := desk.await(func(f Frame) bool { return f.Kind == "event" && f.ID == ref.Stream })
if text := decode[EventWire](t, frame.Payload).Unwire().Text; text != "hello" {
t.Fatalf("the watcher was given %q", text)
}
// And the window that STARTED it is not told about it: it drew that turn the
// moment its own submit answered, and a second adoption would draw the reply
// twice.
for _, frame := range drain(away) {
if frame.Kind == "turn" {
t.Fatalf("the window that started the turn was told about its own turn")
}
}
}
// drain is every frame waiting on a link right now, without waiting for more.
func drain(l *link) []Frame {
var seen []Frame
for {
select {
case frame, ok := <-l.frames:
if !ok {
return seen
}
seen = append(seen, frame)
default:
return seen
}
}
}
// The surface half of the same fact: a watcher is handed the turn on the same
// kind of channel its own submit would have answered with.
func TestAWatchingSurfaceIsHandedTheTurnItDidNotStart(t *testing.T) {
agent := &fakeAgent{}
sess := heldSession(agent)
watcher, err := loopSession(sess, Hello{Surface: "macbook"})
if err != nil {
t.Fatalf("dial: %v", err)
}
defer watcher.Close()
driver, err := loopSession(sess, Hello{Surface: "tower"})
if err != nil {
t.Fatalf("second dial: %v", err)
}
defer driver.Close()
if _, err := driver.Client.Agent().Submit(t.Context(), "say something"); err != nil {
t.Fatalf("submit: %v", err)
}
select {
case turn := <-watcher.Client.Follow():
if turn.Said != "say something" {
t.Fatalf("the watcher was handed a turn opened on %q", turn.Said)
}
agent.stream(0) <- session.Event{Kind: session.EventTextDelta, Text: "something"}
if ev := <-turn.Events; ev.Text != "something" {
t.Fatalf("the turn handed over carried %q", ev.Text)
}
case <-time.After(5 * time.Second):
t.Fatal("the watching surface was never handed the turn")
}
agent.finish(agent.stream(0))
}