fix(droid): align hooks with Factory 0.175
This commit is contained in:
1 parent
827374e7f8
commit
4521cbe32f
15 files changed
+2749
-881
No files matched your search
@@ -1,81 +1,101 @@
|
||||
package plugins
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDroidUninstallPreservesMixedGroupsAndLookalikes(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
installDroidFixture(t, fixture)
|
||||
root := readDroidTestObject(t, fixture.configPath)
|
||||
group := droidManagedGroup(t, root["PreToolUse"], fixture.guardPath)
|
||||
command := droidManagedHandler(t, []any{group}, fixture.guardPath)["command"].(string)
|
||||
group["hooks"] = append(requireDroidArray(t, group["hooks"]), map[string]any{
|
||||
"type": "command", "command": "user-command",
|
||||
})
|
||||
group["owner"] = "user"
|
||||
root["PreToolUse"] = append(requireDroidArray(t, root["PreToolUse"]),
|
||||
map[string]any{
|
||||
"matcher": "*",
|
||||
"hooks": []any{map[string]any{
|
||||
"type": "command", "command": strings.Replace(command, droidGuardScript, droidGuardScript+".backup", 1), "timeout": 10,
|
||||
}},
|
||||
func TestDroidStatusSurfacesMalformedRuntimeIdentity(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*droidFixture)
|
||||
pattern string
|
||||
}{
|
||||
{
|
||||
"malformed config",
|
||||
func(fixture *droidFixture) {
|
||||
if err := os.WriteFile(fixture.runtimeConfig, []byte("{ malformed"), 0600); err != nil {
|
||||
t.Fatalf("corrupt runtime config: %v", err)
|
||||
}
|
||||
},
|
||||
"parse Elydora runtime config",
|
||||
},
|
||||
map[string]any{
|
||||
"matcher": "*",
|
||||
"hooks": []any{map[string]any{
|
||||
"type": "command", "command": strings.Replace(command, "agent-1", "agent-10", 1), "timeout": 10,
|
||||
}},
|
||||
{
|
||||
"unsupported config field",
|
||||
func(fixture *droidFixture) {
|
||||
config := readDroidTestObject(t, fixture.runtimeConfig)
|
||||
config["future"] = true
|
||||
writeDroidTestObject(t, fixture.runtimeConfig, config)
|
||||
},
|
||||
"unsupported field",
|
||||
},
|
||||
{
|
||||
"noncanonical key",
|
||||
func(fixture *droidFixture) {
|
||||
if err := os.WriteFile(fixture.privateKey, []byte("invalid"), 0600); err != nil {
|
||||
t.Fatalf("corrupt private key: %v", err)
|
||||
}
|
||||
},
|
||||
"canonical 32-byte",
|
||||
},
|
||||
)
|
||||
writeDroidTestObject(t, fixture.configPath, root)
|
||||
if err := fixture.plugin.Uninstall(droidTestAgentID); err != nil {
|
||||
t.Fatalf("uninstall Factory Droid hooks: %v", err)
|
||||
}
|
||||
remainingRaw := readDroidTestFile(t, fixture.configPath)
|
||||
for _, marker := range []string{"user-command", droidGuardScript + ".backup", "agent-10"} {
|
||||
if !strings.Contains(remainingRaw, marker) {
|
||||
t.Fatalf("uninstall removed lookalike %q", marker)
|
||||
}
|
||||
}
|
||||
remaining := readDroidTestObject(t, fixture.configPath)
|
||||
if len(requireDroidArray(t, remaining["PostToolUse"])) != 0 {
|
||||
t.Fatalf("PostToolUse after uninstall = %#v", remaining["PostToolUse"])
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
installDroidFixture(t, fixture)
|
||||
test.mutate(fixture)
|
||||
_, err := fixture.plugin.Status()
|
||||
if err == nil || !strings.Contains(err.Error(), test.pattern) {
|
||||
t.Fatalf("status error = %v, want %q", err, test.pattern)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroidInstallRejectsMalformedSourcesBeforeWrites(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hooks *string
|
||||
root *string
|
||||
legacy *string
|
||||
settings *string
|
||||
local *string
|
||||
pattern string
|
||||
}{
|
||||
{"malformed hooks", droidString("{ malformed"), nil, nil, "parse Factory Droid hooks"},
|
||||
{"non-object hooks", droidJSON([]any{}), nil, nil, "JSON object"},
|
||||
{"duplicate event", droidString(`{ "PreToolUse": [], "PreToolUse": [] }`), nil, nil, "duplicate"},
|
||||
{"nested duplicate", droidString(`{ "PreToolUse": [{ "hooks": [], "hooks": [] }] }`), nil, nil, "duplicate"},
|
||||
{"null event", droidString(`{ "PreToolUse": null }`), nil, nil, "must be an array"},
|
||||
{"null group", droidString(`{ "PreToolUse": [null] }`), nil, nil, "must be an object"},
|
||||
{"invalid matcher", droidString(`{ "PreToolUse": [{ "matcher": "[", "hooks": [] }] }`), nil, nil, "regular expression"},
|
||||
{"invalid handler", droidString(`{ "PreToolUse": [{ "hooks": [{ "type": "command", "command": 1 }] }] }`), nil, nil, "must be a string"},
|
||||
{"invalid flag", droidString(`{ "hooksDisabled": "yes" }`), nil, nil, "must be a boolean"},
|
||||
{"unsupported root field", droidString(`{ "theme": "dark" }`), nil, nil, "unsupported field"},
|
||||
{"malformed legacy", nil, droidString("{ malformed"), nil, "legacy hooks"},
|
||||
{"malformed settings", droidString(`{ "PreToolUse": [] }`), nil, droidString("{ malformed"), "settings"},
|
||||
{"null settings hooks", nil, nil, droidString(`{ "hooks": null }`), "JSON object"},
|
||||
{"malformed root", droidString("{ malformed"), nil, nil, nil, "parse Factory Droid hooks"},
|
||||
{"non-object root", droidJSON([]any{}), nil, nil, nil, "JSON object"},
|
||||
{"duplicate event", droidString(`{"hooks":{"PreToolUse":[],"PreToolUse":[]}}`), nil, nil, nil, "duplicate"},
|
||||
{"null event", droidString(`{"hooks":{"PreToolUse":null}}`), nil, nil, nil, "must be an array"},
|
||||
{"null group", droidString(`{"hooks":{"PreToolUse":[null]}}`), nil, nil, nil, "must be an object"},
|
||||
{
|
||||
"invalid matcher",
|
||||
droidString(`{"hooks":{"PreToolUse":[{"matcher":"[","hooks":[]}]}}`),
|
||||
nil, nil, nil, "regular expression",
|
||||
},
|
||||
{
|
||||
"empty handler command",
|
||||
droidString(`{"hooks":{"PreToolUse":[{"hooks":[{"type":"command","command":""}]}]}}`),
|
||||
nil, nil, nil, "non-empty",
|
||||
},
|
||||
{
|
||||
"nonpositive timeout",
|
||||
droidString(`{"hooks":{"PreToolUse":[{"hooks":[{"type":"command","command":"user","timeout":0}]}]}}`),
|
||||
nil, nil, nil, "positive",
|
||||
},
|
||||
{"malformed legacy", nil, droidString("{ malformed"), nil, nil, "legacy hooks"},
|
||||
{"null settings hooks", nil, nil, droidString(`{"hooks":null}`), nil, "JSON object"},
|
||||
{"invalid local flag", nil, nil, nil, droidString(`{"hooksDisabled":"yes"}`), "boolean"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{
|
||||
hooks: test.hooks, legacyHooks: test.legacy, settings: test.settings,
|
||||
root: test.root,
|
||||
legacy: test.legacy,
|
||||
settings: test.settings,
|
||||
localSettings: test.local,
|
||||
})
|
||||
originals := existingDroidSources(t, fixture)
|
||||
err := fixture.plugin.Install(fixture.config)
|
||||
@@ -87,41 +107,57 @@ func TestDroidInstallRejectsMalformedSourcesBeforeWrites(t *testing.T) {
|
||||
t.Fatalf("failed install changed %s", path)
|
||||
}
|
||||
}
|
||||
for _, path := range []string{fixture.hookPath, fixture.runtimeConfig, fixture.privateKey} {
|
||||
for _, path := range []string{
|
||||
fixture.guardPath,
|
||||
fixture.hookPath,
|
||||
fixture.runtimeConfig,
|
||||
fixture.privateKey,
|
||||
} {
|
||||
requireMissingDroidFile(t, path)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroidInstallValidatesManagedPathsBeforeWrites(t *testing.T) {
|
||||
func TestDroidUnknownEventsAndExtensionFieldsRemainValid(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{root: droidJSON(map[string]any{
|
||||
"hooks": map[string]any{
|
||||
"FutureFactoryEvent": []any{map[string]any{
|
||||
"matcher": ".*",
|
||||
"commandRegex": "^factory",
|
||||
"owner": "user",
|
||||
"hooks": []any{map[string]any{
|
||||
"type": "command",
|
||||
"command": "user-command",
|
||||
"timeout": 1,
|
||||
"future": true,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
})})
|
||||
installDroidFixture(t, fixture)
|
||||
hooks := droidCurrentHooks(t, fixture.configPath)
|
||||
future := requireDroidObject(t, requireDroidArray(t, hooks["FutureFactoryEvent"])[0])
|
||||
if future["owner"] != "user" {
|
||||
t.Fatalf("future event = %#v", future)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroidInstallValidatesConfigurationBeforeWrites(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*droidFixture)
|
||||
pattern string
|
||||
}{
|
||||
{"missing organization", func(f *droidFixture) { f.config.OrgID = "" }, "organization ID is required"},
|
||||
{"blank key ID", func(f *droidFixture) { f.config.KID = " " }, "key ID is required"},
|
||||
{"invalid private key", func(f *droidFixture) { f.config.PrivateKey = "invalid" }, "canonical 32-byte"},
|
||||
{"invalid base URL", func(f *droidFixture) { f.config.BaseURL = "relative" }, "absolute HTTP or HTTPS"},
|
||||
{"invalid agent ID", func(f *droidFixture) { f.config.AgentID = "../agent" }, "single non-empty path segment"},
|
||||
{
|
||||
name: "missing guard",
|
||||
mutate: func(fixture *droidFixture) {
|
||||
if err := os.Remove(fixture.guardPath); err != nil {
|
||||
t.Fatalf("remove guard: %v", err)
|
||||
}
|
||||
},
|
||||
pattern: "guard runtime is missing",
|
||||
},
|
||||
{
|
||||
name: "invalid agent id",
|
||||
mutate: func(fixture *droidFixture) {
|
||||
fixture.config.AgentID = "../agent"
|
||||
},
|
||||
pattern: "single non-empty path segment",
|
||||
},
|
||||
{
|
||||
name: "guard outside managed directory",
|
||||
mutate: func(fixture *droidFixture) {
|
||||
fixture.config.GuardScriptPath = filepath.Join(fixture.homeDir, "guard.js")
|
||||
},
|
||||
pattern: "managed agent directory",
|
||||
"guard outside managed directory",
|
||||
func(f *droidFixture) { f.config.GuardScriptPath = filepath.Join(f.homeDir, "guard.js") },
|
||||
"managed agent directory",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
@@ -132,111 +168,145 @@ func TestDroidInstallValidatesManagedPathsBeforeWrites(t *testing.T) {
|
||||
if err == nil || !strings.Contains(err.Error(), test.pattern) {
|
||||
t.Fatalf("install error = %v, want substring %q", err, test.pattern)
|
||||
}
|
||||
for _, path := range []string{fixture.configPath, fixture.hookPath, fixture.runtimeConfig, fixture.privateKey} {
|
||||
requireMissingDroidFile(t, path)
|
||||
}
|
||||
requireMissingDroidFile(t, fixture.configPath)
|
||||
requireMissingDroidFile(t, fixture.runtimeConfig)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDroidTransactionRollsBackAllFilesAndCleansStaging(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{
|
||||
hooks: droidJSON(map[string]any{"PreToolUse": []any{}}),
|
||||
settings: droidJSON(map[string]any{"hooks": map[string]any{"PostToolUse": []any{}}}),
|
||||
})
|
||||
originalRoot := readDroidTestFile(t, fixture.configPath)
|
||||
originalSettings := readDroidTestFile(t, fixture.settingsPath)
|
||||
failed := false
|
||||
fixture.plugin.rename = func(source, destination string) error {
|
||||
if !failed && sameDroidPath(destination, fixture.settingsPath) {
|
||||
failed = true
|
||||
return errors.New("simulated settings commit failure")
|
||||
}
|
||||
return os.Rename(source, destination)
|
||||
}
|
||||
err := fixture.plugin.Install(fixture.config)
|
||||
if err == nil || !strings.Contains(err.Error(), "Write Factory Droid installation") || !failed {
|
||||
t.Fatalf("transaction error = %v, failed = %v", err, failed)
|
||||
}
|
||||
if readDroidTestFile(t, fixture.configPath) != originalRoot ||
|
||||
readDroidTestFile(t, fixture.settingsPath) != originalSettings {
|
||||
t.Fatal("transaction rollback did not restore hook sources")
|
||||
}
|
||||
for _, path := range []string{fixture.hookPath, fixture.runtimeConfig, fixture.privateKey} {
|
||||
requireMissingDroidFile(t, path)
|
||||
}
|
||||
requireNoDroidStagingFiles(t, fixture.homeDir)
|
||||
}
|
||||
|
||||
func TestDroidTransactionDetectsExternalChangesAndPreservesThem(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{
|
||||
hooks: droidJSON(map[string]any{"PreToolUse": []any{}}),
|
||||
settings: droidJSON(map[string]any{"hooks": map[string]any{"PostToolUse": []any{}}}),
|
||||
})
|
||||
external := "{\n \"external\": true,\n \"hooks\": { \"PostToolUse\": [] }\n}\n"
|
||||
mutated := false
|
||||
fixture.plugin.rename = func(source, destination string) error {
|
||||
if !mutated {
|
||||
mutated = true
|
||||
if err := os.WriteFile(fixture.settingsPath, []byte(external), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return os.Rename(source, destination)
|
||||
}
|
||||
err := fixture.plugin.Install(fixture.config)
|
||||
if err == nil || !strings.Contains(err.Error(), "changed during installation") {
|
||||
t.Fatalf("external-change error = %v", err)
|
||||
}
|
||||
if readDroidTestFile(t, fixture.settingsPath) != external {
|
||||
t.Fatal("transaction rollback overwrote an external settings change")
|
||||
}
|
||||
for _, path := range []string{fixture.hookPath, fixture.runtimeConfig, fixture.privateKey} {
|
||||
requireMissingDroidFile(t, path)
|
||||
}
|
||||
requireNoDroidStagingFiles(t, fixture.homeDir)
|
||||
}
|
||||
|
||||
func TestDroidRecoveryCommandsDoNotRequireNodeResolution(t *testing.T) {
|
||||
func TestDroidOrphanedRuntimeIsPreservedWithoutVerifiableIdentity(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
installDroidFixture(t, fixture)
|
||||
t.Setenv("PATH", "")
|
||||
status, err := fixture.plugin.Status()
|
||||
if err != nil || !status.Installed {
|
||||
t.Fatalf("status without PATH = %#v, %v", status, err)
|
||||
if err := os.MkdirAll(fixture.agentDir, 0700); err != nil {
|
||||
t.Fatalf("create orphaned runtime: %v", err)
|
||||
}
|
||||
if err := fixture.plugin.Uninstall(droidTestAgentID); err != nil {
|
||||
t.Fatalf("uninstall without PATH: %v", err)
|
||||
if err := os.WriteFile(fixture.guardPath, []byte("orphaned guard\n"), 0700); err != nil {
|
||||
t.Fatalf("write orphaned guard: %v", err)
|
||||
}
|
||||
err := fixture.plugin.Install(fixture.config)
|
||||
if err == nil || !strings.Contains(err.Error(), "identity cannot be verified") {
|
||||
t.Fatalf("orphaned runtime error = %v", err)
|
||||
}
|
||||
if readDroidTestFile(t, fixture.guardPath) != "orphaned guard\n" {
|
||||
t.Fatal("orphaned guard changed")
|
||||
}
|
||||
requireMissingDroidFile(t, fixture.configPath)
|
||||
}
|
||||
|
||||
func TestDroidStatusSurfacesMalformedRuntimeConfig(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
func TestDroidUninstallPreservesUsersAndExactOwnership(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{root: droidJSON(map[string]any{
|
||||
"hooks": map[string]any{"Notification": []any{}},
|
||||
})})
|
||||
installDroidFixture(t, fixture)
|
||||
if err := os.WriteFile(fixture.runtimeConfig, []byte("{ malformed"), 0600); err != nil {
|
||||
t.Fatalf("corrupt runtime config: %v", err)
|
||||
root := readDroidTestObject(t, fixture.configPath)
|
||||
hooks := requireDroidObject(t, root["hooks"])
|
||||
group := droidManagedGroup(t, hooks["PreToolUse"], fixture.guardPath)
|
||||
command := droidManagedHandler(t, []any{group}, fixture.guardPath)["command"].(string)
|
||||
group["hooks"] = append(requireDroidArray(t, group["hooks"]), map[string]any{
|
||||
"type": "command", "command": "user-command",
|
||||
})
|
||||
group["owner"] = "user"
|
||||
hooks["PreToolUse"] = append(requireDroidArray(t, hooks["PreToolUse"]),
|
||||
map[string]any{
|
||||
"matcher": "*",
|
||||
"hooks": []any{map[string]any{
|
||||
"type": "command",
|
||||
"command": strings.Replace(command, droidGuardScript, droidGuardScript+".backup", 1),
|
||||
"timeout": 10,
|
||||
}},
|
||||
},
|
||||
map[string]any{
|
||||
"matcher": "*",
|
||||
"hooks": []any{map[string]any{
|
||||
"type": "command",
|
||||
"command": strings.Replace(command, droidTestAgentID, "agent-10", 1),
|
||||
"timeout": 10,
|
||||
}},
|
||||
},
|
||||
)
|
||||
writeDroidTestObject(t, fixture.configPath, root)
|
||||
agentID := droidTestAgentID
|
||||
if runtime.GOOS == "windows" {
|
||||
agentID = strings.ToUpper(agentID)
|
||||
}
|
||||
if _, err := fixture.plugin.Status(); err == nil || !strings.Contains(err.Error(), "parse Elydora runtime config") {
|
||||
t.Fatalf("status error = %v", err)
|
||||
if err := fixture.plugin.Uninstall(agentID); err != nil {
|
||||
t.Fatalf("uninstall Factory Droid hooks: %v", err)
|
||||
}
|
||||
remaining := readDroidTestFile(t, fixture.configPath)
|
||||
for _, marker := range []string{"user-command", droidGuardScript + ".backup", "agent-10"} {
|
||||
if !strings.Contains(remaining, marker) {
|
||||
t.Fatalf("uninstall removed %q", marker)
|
||||
}
|
||||
}
|
||||
currentHooks := droidCurrentHooks(t, fixture.configPath)
|
||||
if _, exists := currentHooks["PostToolUse"]; exists {
|
||||
t.Fatalf("managed PostToolUse remains: %#v", currentHooks)
|
||||
}
|
||||
}
|
||||
|
||||
func writeDroidTestObject(t *testing.T, path string, value map[string]any) {
|
||||
t.Helper()
|
||||
encoded, err := json.MarshalIndent(value, "", " ")
|
||||
if err != nil {
|
||||
t.Fatalf("encode %s: %v", path, err)
|
||||
func TestDroidUninstallRemovesOwnedEmptyFileAndKeepsAbsence(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
installDroidFixture(t, fixture)
|
||||
if err := fixture.plugin.Uninstall(droidTestAgentID); err != nil {
|
||||
t.Fatalf("uninstall Factory Droid hooks: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(path, append(encoded, '\n'), 0600); err != nil {
|
||||
t.Fatalf("write %s: %v", path, err)
|
||||
requireMissingDroidFile(t, fixture.configPath)
|
||||
|
||||
empty := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
if err := empty.plugin.Uninstall(droidTestAgentID); err != nil {
|
||||
t.Fatalf("uninstall absent hooks: %v", err)
|
||||
}
|
||||
requireMissingDroidFile(t, empty.configPath)
|
||||
}
|
||||
|
||||
func TestDroidInstallRejectsLinkedPathsBeforeWrites(t *testing.T) {
|
||||
for _, kind := range []string{"factory", "hook", "runtime"} {
|
||||
t.Run(kind, func(t *testing.T) {
|
||||
fixture := prepareDroidFixture(t, droidFixtureOptions{})
|
||||
target := filepath.Join(t.TempDir(), kind+"-target")
|
||||
if err := os.MkdirAll(target, 0755); err != nil {
|
||||
t.Fatalf("create symlink target: %v", err)
|
||||
}
|
||||
var linkErr error
|
||||
switch kind {
|
||||
case "factory":
|
||||
linkErr = os.MkdirAll(fixture.homeDir, 0755)
|
||||
if linkErr == nil {
|
||||
linkErr = os.Symlink(target, fixture.factoryDir)
|
||||
}
|
||||
case "hook":
|
||||
if err := os.MkdirAll(fixture.factoryDir, 0755); err != nil {
|
||||
t.Fatalf("create Factory directory: %v", err)
|
||||
}
|
||||
targetFile := filepath.Join(target, "hooks.json")
|
||||
writeDroidTestObject(t, targetFile, map[string]any{"hooks": map[string]any{}})
|
||||
linkErr = os.Symlink(targetFile, fixture.configPath)
|
||||
case "runtime":
|
||||
linkErr = os.MkdirAll(fixture.homeDir, 0755)
|
||||
if linkErr == nil {
|
||||
linkErr = os.Symlink(target, filepath.Join(fixture.homeDir, ".elydora"))
|
||||
}
|
||||
}
|
||||
if linkErr != nil {
|
||||
t.Skipf("symbolic links unavailable: %v", linkErr)
|
||||
}
|
||||
err := fixture.plugin.Install(fixture.config)
|
||||
if err == nil || !strings.Contains(err.Error(), "physical") {
|
||||
t.Fatalf("linked-path error = %v", err)
|
||||
}
|
||||
requireMissingDroidFile(t, fixture.runtimeConfig)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func existingDroidSources(t *testing.T, fixture *droidFixture) map[string]string {
|
||||
t.Helper()
|
||||
result := map[string]string{}
|
||||
for _, path := range []string{fixture.configPath, fixture.legacyPath, fixture.settingsPath} {
|
||||
for _, path := range []string{
|
||||
fixture.configPath,
|
||||
fixture.legacyPath,
|
||||
fixture.settingsPath,
|
||||
fixture.localSettingsPath,
|
||||
} {
|
||||
if raw, err := os.ReadFile(path); err == nil {
|
||||
result[path] = string(raw)
|
||||
} else if !errors.Is(err, os.ErrNotExist) {
|
||||
@@ -245,19 +315,3 @@ func existingDroidSources(t *testing.T, fixture *droidFixture) map[string]string
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func requireNoDroidStagingFiles(t *testing.T, root string) {
|
||||
t.Helper()
|
||||
err := filepath.WalkDir(root, func(path string, entry fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasSuffix(entry.Name(), ".tmp") || strings.HasSuffix(entry.Name(), ".rollback") {
|
||||
t.Errorf("staging file remains: %s", path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("walk staging files: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user