package resolution import ( "strings" "testing" ) // A `user` shape and a user-scoped unit name the operator account the way a home file does // (novox/hq ADR 0176, ADR 0177): with ${machine:account}, resolved when the module is assigned. func TestAUserShapeAndAUserScopedUnitNameTheAccount(t *testing.T) { facts := map[string]string{"account": "ops", "account-home": "/home/ops"} login := map[string]any{"type": "user", "id": "login", "name": "${machine:account}", "shell": "/usr/bin/zsh"} if err := machineInto(login, facts, "zsh"); err != nil { t.Fatal(err) } if login["name"] != "ops" { t.Fatalf("the user shape did not learn the account: %v", login["name"]) } watcher := map[string]any{"type": "service", "id": "watcher", "unit": "i3-reload-watcher.service", "scope": "user", "user": "${machine:account}"} if err := machineInto(watcher, facts, "i3"); err != nil { t.Fatal(err) } if watcher["user"] != "ops" { t.Fatalf("the user-scoped unit did not learn the account: %v", watcher["user"]) } // A machine with no operator account refuses rather than writing the literal. err := machineInto(map[string]any{"type": "user", "id": "login", "name": "${machine:account}"}, map[string]string{"address": "10.0.0.1"}, "zsh") if err == nil || !strings.Contains(err.Error(), "${machine:account}") { t.Fatalf("a user shape on a machine with no account was not refused by name: %v", err) } }