package apply import ( "strings" "testing" "github.com/novox/mesh-host/internal/declaration" ) func aDaemon() *declaration.Daemon { return &declaration.Daemon{ ID: "server", Type: declaration.TypeDaemon, Name: "greeter", Source: "https://store.invalid/greeter/daemon", Digest: "sha256:" + strings.Repeat("a", 64), Run: []string{"node", "index.js"}, Env: map[string]string{"MESH_NODE": "anchor", "A_FIRST": "1"}, } } // The unit the mesh writes says what it runs, where, and that it comes back. func TestTheUnitRunsWhatTheDaemonSaid(t *testing.T) { unit := unitFor(aDaemon()) for _, want := range []string{ "ExecStart=node index.js", "WorkingDirectory=/var/lib/mesh/daemons/greeter", "Restart=always", "WantedBy=multi-user.target", } { if !strings.Contains(unit, want) { t.Fatalf("the unit does not say %q:\n%s", want, unit) } } } // **Generated whole and saying so.** Every managed file on a machine carries this, because an edit // that survives until the next declaration and then vanishes is worse than one that is refused. func TestTheUnitSaysItIsTheMeshs(t *testing.T) { unit := unitFor(aDaemon()) if !strings.HasPrefix(unit, "#") || !strings.Contains(unit, "Do not edit") { t.Fatalf("the unit does not say it is generated:\n%s", unit) } } // **Deterministic, because the unit is half the daemon's identity.** Environment held in a map // would be written in Go's iteration order, so every apply would see a different unit and call an // unchanged daemon changed — restarting it on every declaration for ever. func TestTheUnitIsTheSameEveryTime(t *testing.T) { first := unitFor(aDaemon()) for i := 0; i < 20; i++ { if again := unitFor(aDaemon()); again != first { t.Fatalf("two renderings of one daemon differ:\n%s\n---\n%s", first, again) } } // And sorted, so the order is a decision rather than luck. if strings.Index(first, "A_FIRST") > strings.Index(first, "MESH_NODE") { t.Fatalf("environment is not in a stable order:\n%s", first) } } // **Two daemons from one bundle differing only in their command are different daemons.** Tracking // the digest alone would call the second one unchanged and leave the first one running. func TestADaemonsIdentityIncludesHowItIsRun(t *testing.T) { one := aDaemon() two := aDaemon() two.Run = []string{"node", "other.js"} if unitFor(one) == unitFor(two) { t.Fatal("two daemons with different commands render one unit, so a change would be missed") } } // A daemon that runs as somebody says so, and one that does not says nothing — rather than naming // root explicitly, which would be a claim the mesh does not need to make. func TestADaemonRunsAsWhoItSaid(t *testing.T) { as := aDaemon() as.User = "greeter" if !strings.Contains(unitFor(as), "User=greeter") { t.Fatalf("the unit does not run as the user it named:\n%s", unitFor(as)) } if strings.Contains(unitFor(aDaemon()), "User=") { t.Fatalf("a daemon that named no user had one written for it:\n%s", unitFor(aDaemon())) } }