Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

392 commit(s) on main

Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys keenan · 2h ago 4b8c9e1d
history blame raw 2.3 KiB
1package agent
2
3import (
4 "bufio"
5 "encoding/json"
6 "io"
7 "testing"
8)
9
10// captureSession is a session with no ssh under it that records the requests it is
11// given, so a test can say what the runner asked for and not only what it did with
12// the answer. One reply is written per request.
13func captureSession(t *testing.T, reqs chan<- runnerRequest, replies ...runnerReply) *runnerSession {
14 t.Helper()
15 reqR, reqW := io.Pipe()
16 repR, repW := io.Pipe()
17 go func() {
18 defer repW.Close()
19 dec := json.NewDecoder(reqR)
20 enc := json.NewEncoder(repW)
21 for _, reply := range replies {
22 var req runnerRequest
23 if err := dec.Decode(&req); err != nil {
24 return
25 }
26 select {
27 case reqs <- req:
28 default:
29 }
30 if err := enc.Encode(reply); err != nil {
31 return
32 }
33 }
34 }()
35 t.Cleanup(func() { _ = reqW.Close() })
36 return &runnerSession{
37 in: bufio.NewWriter(reqW),
38 out: bufio.NewReader(repR),
39 enc: json.NewEncoder(reqW),
40 dec: json.NewDecoder(repR),
41 }
42}
43
44// The renewal between steps has to be the request the server expects, carrying the
45// run it belongs to: the whole point of the step boundary is that no command is
46// running to send it.
47func TestHeartbeatBetweenStepsNamesTheRun(t *testing.T) {
48 t.Parallel()
49 for _, held := range []bool{true, false} {
50 reqs := make(chan runnerRequest, 1)
51 s := captureSession(t, reqs, runnerReply{Op: "heartbeat", OK: held})
52 if got := s.heartbeat("run-1"); got != held {
53 t.Fatalf("heartbeat = %v, want %v", got, held)
54 }
55 select {
56 case req := <-reqs:
57 if req.Op != "heartbeat" || req.Run != "run-1" {
58 t.Fatalf("heartbeat sent %+v; want op=heartbeat run=run-1", req)
59 }
60 default:
61 t.Fatal("heartbeat sent no request")
62 }
63 }
64}
65
66// A heartbeat that cannot be sent is not a lease: the attempt must stop rather than
67// run a step the queue may already have given to another runner.
68func TestHeartbeatWithoutAConnectionIsNotHeld(t *testing.T) {
69 t.Parallel()
70 reqR, reqW := io.Pipe()
71 repR, repW := io.Pipe()
72 _ = reqR.Close()
73 _ = repW.Close()
74 t.Cleanup(func() { _ = reqW.Close(); _ = repR.Close() })
75 s := &runnerSession{
76 in: bufio.NewWriter(reqW),
77 out: bufio.NewReader(repR),
78 enc: json.NewEncoder(reqW),
79 dec: json.NewDecoder(repR),
80 }
81 if s.heartbeat("run-1") {
82 t.Fatal("a heartbeat on a dead connection reported the lease as held")
83 }
84}
85