Files
mesh-host/internal/processbuilds/processbuilds_test.go
T

71 lines
3.1 KiB
Go

package processbuilds
import (
"context"
"errors"
"strings"
"testing"
"git.novox.be/novox/mesh-sdk/go/declaration"
)
// Design 47, *The fingerprint handover*: the build of a daemon is read from its running process's environment and of a
// container from its configuration, narrowed by module; one started without the value, one not running and one the
// runtime cannot read each say why their build is unknown, never a guessed fingerprint.
func TestProcessBuildsAreReadFromTheRunningProcesses(t *testing.T) {
fp := "src2:" + strings.Repeat("a", 64)
d := &declaration.Declaration{Resources: []declaration.Resource{
&declaration.Process{ID: "web.d", Type: declaration.TypeProcess, Module: "web", Name: "web-d"},
&declaration.Process{ID: "old.d", Type: declaration.TypeProcess, Module: "old", Name: "old-d"},
&declaration.Process{ID: "down.d", Type: declaration.TypeProcess, Module: "down", Name: "down-d"},
&declaration.Container{ID: "db.c", Type: declaration.TypeContainer, Module: "db", Name: "db-c"},
&declaration.Container{ID: "gone.c", Type: declaration.TypeContainer, Module: "gone", Name: "gone-c"},
&declaration.Directory{ID: "web.dir", Type: declaration.TypeDirectory, Module: "web"},
}}
run := func(_ context.Context, name string, args ...string) (string, error) {
switch {
case name == "systemctl" && args[len(args)-1] == "web-d.service":
return "MainPID=11\nActiveEnterTimestamp=Mon 2026-11-09 10:00:00 UTC\n", nil
case name == "systemctl" && args[len(args)-1] == "old-d.service":
return "MainPID=12\nActiveEnterTimestamp=\n", nil
case name == "systemctl":
return "MainPID=0\nActiveEnterTimestamp=\n", nil
case name == "docker" && args[len(args)-1] == "db-c":
return `["A=1","MESH_FINGERPRINT=` + fp + `"]` + "\t2026-11-09T10:00:00.5Z\n", nil
}
return "", errors.New("no such container")
}
environ := func(pid int) ([]byte, error) {
if pid == 11 {
return []byte("A=1\x00MESH_FINGERPRINT=" + fp + "\x00"), nil
}
return []byte("A=1\x00"), nil
}
r := Reader{Node: "n1", Run: run, Environ: environ}
got := r.Read(context.Background(), d, "")
by := map[string]string{}
for _, p := range got.Processes {
by[p.Module] = p.Fingerprint + "|" + p.Unknown
}
want := map[string]string{"web": fp + "|", "db": fp + "|",
"old": "|started before the node-engine handed MESH_FINGERPRINT, or without it",
"down": "|the unit runs no process now", "gone": "|the container cannot be read: no such container"}
if len(by) != len(want) || got.Node != "n1" {
t.Fatalf("read %v, want %v", by, want)
}
for m, w := range want {
if by[m] != w {
t.Errorf("%s: %q, want %q", m, by[m], w)
}
}
if got.Processes[0].Module != "db" || got.Processes[len(got.Processes)-1].Module != "web" || got.Processes[len(got.Processes)-1].Started == nil {
t.Errorf("order or start time wrong: %+v", got.Processes)
}
if one := r.Read(context.Background(), d, "web"); len(one.Processes) != 1 || one.Processes[0].Process != "web-d.service" {
t.Errorf("narrowed by module: %+v", one.Processes)
}
if none := r.Read(context.Background(), nil, ""); none.Error == "" || none.Processes == nil {
t.Errorf("no declaration: %+v", none)
}
}