A watch that died left the block silent, a removed block kept its value, and a value frozen at its source looked fresh because its file was new. The follower now rereads a silent value and says so, drops removed blocks, and dates each file by the reading's own time. The path check takes /etc and /usr/local/lib in, ignores what a container sees inside itself, and lists the five findings standing today, which may only go.
110 lines
4.0 KiB
Go
110 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func catalogue(t *testing.T, files map[string]string) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
for p, c := range files {
|
|
full := filepath.Join(root, p)
|
|
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(full, []byte(c), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
return root
|
|
}
|
|
|
|
const owner = `{"module":"power","resources":[{"id":"d","type":"directory","path":"/run/mesh-power"}]}`
|
|
|
|
func TestAModuleReadingAnothersStateIsFound(t *testing.T) {
|
|
root := catalogue(t, map[string]string{
|
|
"modules/power/module.json": owner,
|
|
"modules/power/cmd/power/draw.go": `const f = "/run/mesh-power/draw"`,
|
|
"modules/bar/module.json": `{"module":"bar","resources":[{"id":"x","type":"file","path":"/etc/x","content":"cat /run/mesh-power/draw"}]}`,
|
|
"modules/other/module.json": `{"module":"other"}`,
|
|
"modules/other/files/bin/read": "#!/bin/sh\ncat /run/mesh-power\n",
|
|
"modules/other/README.md": "it once read /run/mesh-power/draw",
|
|
"modules/other/cmd/x/x_test.go": `"/run/mesh-power"`,
|
|
"modules/near/module.json": `{"module":"near","resources":[{"id":"y","type":"file","path":"/etc/y","content":"/run/mesh-power-other/x"}]}`,
|
|
})
|
|
found, err := Check(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var got []string
|
|
for _, f := range found {
|
|
got = append(got, f.Module+" "+f.File)
|
|
}
|
|
want := []string{"bar modules/bar/module.json", "other modules/other/files/bin/read"}
|
|
if strings.Join(got, "|") != strings.Join(want, "|") {
|
|
t.Fatalf("found %v, want %v", got, want)
|
|
}
|
|
if !strings.Contains(found[0].String(), "power's") {
|
|
t.Fatalf("%s", found[0])
|
|
}
|
|
}
|
|
|
|
func TestACatalogueWhereEachKeepsToItsOwnIsClean(t *testing.T) {
|
|
root := catalogue(t, map[string]string{
|
|
"modules/power/module.json": owner,
|
|
"modules/power/cmd/power/draw.go": `const f = "/run/mesh-power/draw"`,
|
|
})
|
|
if found, err := Check(root); err != nil || len(found) != 0 {
|
|
t.Fatalf("%v %v", found, err)
|
|
}
|
|
}
|
|
|
|
func TestEtcAndUsrLocalLibAreAModulesTooButNotInsideAContainer(t *testing.T) {
|
|
root := catalogue(t, map[string]string{
|
|
"modules/power/module.json": `{"module":"power","resources":[{"id":"m","type":"directory","path":"/etc/mesh-power/moments"},` +
|
|
`{"id":"s","type":"archive","path":"/usr/local/lib/mesh-power"}]}`,
|
|
"modules/reader/module.json": `{"module":"reader"}`,
|
|
"modules/reader/cmd/r/r.go": `const a, b = "/etc/mesh-power/moments/after-wake", "/usr/local/lib/mesh-power/bin/x"`,
|
|
// A container that mounts something at that path inside itself names its own world.
|
|
"modules/boxed/module.json": `{"module":"boxed","resources":[{"id":"c","type":"container",` +
|
|
`"volumes":["/srv/boxed:/etc/mesh-power/moments",{"source":"/srv/b","target":"/usr/local/lib/mesh-power"}]}]}`,
|
|
// A binary says what its source says.
|
|
"modules/boxed/bin/tool": "\x00\x01/etc/mesh-power/moments\x00",
|
|
})
|
|
found, err := Check(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var got []string
|
|
for _, f := range found {
|
|
got = append(got, f.Module+" "+f.Path)
|
|
}
|
|
want := []string{"reader /etc/mesh-power/moments", "reader /usr/local/lib/mesh-power"}
|
|
if strings.Join(got, "|") != strings.Join(want, "|") {
|
|
t.Fatalf("found %v, want %v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestSharedPathsPassAndKnownFindingsOnlyShrink(t *testing.T) {
|
|
found := []Finding{
|
|
{Module: "dns", File: "modules/dns/module.json", Path: "/etc/hosts", Owner: "hostname"},
|
|
{Module: "laptop", File: "modules/laptop/k.go", Path: "/etc/triggers", Owner: "keys"},
|
|
{Module: "new", File: "modules/new/n.go", Path: "/run/mesh-power", Owner: "power"},
|
|
}
|
|
shared := map[string]bool{"/etc/hosts": true}
|
|
known := map[string]bool{
|
|
"laptop /etc/triggers modules/laptop/k.go": true,
|
|
"old /run/x modules/old/o.go": true,
|
|
}
|
|
refused, gone := Judge(found, shared, known)
|
|
if len(refused) != 1 || refused[0].Module != "new" {
|
|
t.Fatalf("refused %v", refused)
|
|
}
|
|
if len(gone) != 1 || gone[0] != "old /run/x modules/old/o.go" {
|
|
t.Fatalf("gone %v", gone)
|
|
}
|
|
}
|