carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package activator
4
5import (
6 "errors"
7 "os"
8 "os/exec"
9 "testing"
10 "time"
11
12 "github.com/carlosframework/platform/internal/hostbox"
13)
14
15// startSleep starts a child that lives until the test ends and returns it
16// with a channel closed once it is reaped.
17func startSleep(t *testing.T) (*exec.Cmd, chan struct{}) {
18 t.Helper()
19 child := exec.Command("sleep", "30")
20 if err := child.Start(); err != nil {
21 t.Skip("no sleep binary:", err)
22 }
23 reaped := make(chan struct{})
24 go func() { _ = child.Wait(); close(reaped) }()
25 t.Cleanup(func() { _ = child.Process.Kill(); <-reaped })
26 return child, reaped
27}
28
29// The pin opens the handle before it reads the start, refuses a start that
30// is not the grant's, and hands the watcher the same pinned process.
31func TestPlan11PinRootProcessChecksTheGrantStart(t *testing.T) {
32 child, reaped := startSleep(t)
33 pid := child.Process.Pid
34 start, err := roleProcessStart(pid)
35 if err != nil {
36 t.Fatal(err)
37 }
38 if _, err := pinRootProcess(pid, start+"1"); !errors.Is(err, hostbox.ErrChanged) {
39 t.Fatalf("other start: %v", err)
40 }
41 proc, err := pinRootProcess(pid, start)
42 if err != nil {
43 t.Fatal(err)
44 }
45 if err := proc.WithHandle(func(uintptr) {}); err != nil {
46 t.Fatalf("pinned process has no handle: %v", err)
47 }
48 p := newClaimProcessFor(&exec.Cmd{Process: proc}, nil, true)
49 time.Sleep(50 * time.Millisecond)
50 if p.Exited() {
51 t.Fatal("running root process reported exited")
52 }
53 _ = child.Process.Kill()
54 <-reaped
55 select {
56 case <-p.done:
57 case <-time.After(5 * time.Second):
58 t.Fatal("exit of the pinned process was missed")
59 }
60 // The pid is gone (ESRCH): the grant's process has exited, so the
61 // watcher reports an exit rather than a launch failure.
62 gone, err := pinRootProcess(pid, start)
63 if err != nil {
64 t.Fatalf("gone process: %v", err)
65 }
66 q := newClaimProcessFor(&exec.Cmd{Process: gone}, nil, true)
67 select {
68 case <-q.done:
69 case <-time.After(5 * time.Second):
70 t.Fatal("gone root process not reported exited")
71 }
72}
73
74// A root process the agent holds no pinned handle for is not watchable. It
75// must never read as exited.
76func TestPlan11RootWatchWithoutHandleIsNotExit(t *testing.T) {
77 child, _ := startSleep(t)
78 proc, err := os.FindProcess(child.Process.Pid)
79 if err != nil {
80 t.Fatal(err)
81 }
82 if err := proc.Release(); err != nil {
83 t.Fatal(err)
84 }
85 p := newClaimProcessFor(&exec.Cmd{Process: proc}, nil, true)
86 time.Sleep(50 * time.Millisecond)
87 if p.Exited() {
88 t.Fatal("unwatchable root process reported exited")
89 }
90}
91