Files
Elydora-Go-SDK/cmd/elydora/plugins/copilot_transaction_test.go

249 lines
8.3 KiB
Go

package plugins
import (
"errors"
"os"
"path/filepath"
"strings"
"testing"
)
func TestCopilotPrepareRejectsSameContentStaleHookSnapshot(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{
userRaw: copilotJSON(map[string]any{
"version": float64(1),
"hooks": map[string]any{"notification": []any{}},
}),
})
sources, _, err := readCopilotSources()
if err != nil {
t.Fatalf("read GitHub Copilot sources: %v", err)
}
paths, nodePath, err := preflightCopilotInstallation(fixture.config, sources)
if err != nil {
t.Fatalf("preflight GitHub Copilot installation: %v", err)
}
rendered, err := renderCopilotInstallation(
sources,
paths.guardPath,
paths.auditPath,
nodePath,
)
if err != nil {
t.Fatalf("render GitHub Copilot installation: %v", err)
}
original, err := os.ReadFile(fixture.configPath)
if err != nil {
t.Fatalf("read user hooks: %v", err)
}
replacement := fixture.configPath + ".replacement"
if err := os.WriteFile(replacement, original, 0600); err != nil {
t.Fatalf("write replacement hooks: %v", err)
}
if err := os.Rename(replacement, fixture.configPath); err != nil {
t.Fatalf("replace user hooks: %v", err)
}
_, err = prepareCopilotInstallation(fixture.config, sources, rendered)
if err == nil || !strings.Contains(err.Error(), "changed before update") {
t.Fatalf("prepare error = %v", err)
}
assertCopilotRuntimeAbsent(t, fixture)
}
func TestCopilotInstallRollsBackWhenEffectiveSettingsChange(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{
userSettingsRaw: copilotJSON(map[string]any{"disableAllHooks": false}),
})
commits := 0
mutated := false
fixture.plugin.rename = func(source, destination string) error {
if err := os.Rename(source, destination); err != nil {
return err
}
if !mutated && strings.HasSuffix(source, ".tmp") {
commits++
if commits == 3 {
mutated = true
writeCopilotObject(t, fixture.userSettings, map[string]any{
"disableAllHooks": true,
})
}
}
return nil
}
err := fixture.plugin.Install(fixture.config)
if err == nil || !strings.Contains(err.Error(), "user settings changed") {
t.Fatalf("install error = %v", err)
}
settings := readCopilotObject(t, fixture.userSettings)
if settings["disableAllHooks"] != true {
t.Fatalf("concurrent settings = %#v", settings)
}
if _, err := os.Lstat(fixture.configPath); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("hook source exists after rollback: %v", err)
}
assertCopilotRuntimeAbsent(t, fixture)
assertNoCopilotTransactionArtifacts(t, fixture.homeDir, fixture.projectDir)
}
func TestCopilotIdempotentCommitChecksSameContentSettingsIdentity(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{
userSettingsRaw: copilotJSON(map[string]any{"disableAllHooks": false}),
})
installCopilotFixture(t, fixture)
sources, _, err := readCopilotSources()
if err != nil {
t.Fatalf("read GitHub Copilot sources: %v", err)
}
paths, nodePath, err := preflightCopilotInstallation(fixture.config, sources)
if err != nil {
t.Fatalf("preflight GitHub Copilot installation: %v", err)
}
rendered, err := renderCopilotInstallation(
sources,
paths.guardPath,
paths.auditPath,
nodePath,
)
if err != nil {
t.Fatalf("render GitHub Copilot installation: %v", err)
}
prepared, err := prepareCopilotInstallation(fixture.config, sources, rendered)
if err != nil {
t.Fatalf("prepare GitHub Copilot installation: %v", err)
}
original, err := os.ReadFile(fixture.userSettings)
if err != nil {
t.Fatalf("read user settings: %v", err)
}
replacement := fixture.userSettings + ".replacement"
if err := os.WriteFile(replacement, original, 0600); err != nil {
t.Fatalf("write replacement settings: %v", err)
}
if err := os.Rename(replacement, fixture.userSettings); err != nil {
t.Fatalf("replace user settings: %v", err)
}
err = commitCopilotInstallation(prepared, fixture.plugin.rename)
if err == nil || !strings.Contains(err.Error(), "user settings changed") {
t.Fatalf("commit error = %v", err)
}
}
func TestCopilotInstallPreservesOrphanedRuntimeWithoutIdentity(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{})
if err := os.MkdirAll(fixture.agentDir, 0700); err != nil {
t.Fatalf("create agent runtime directory: %v", err)
}
if err := os.WriteFile(fixture.hookPath, []byte("orphaned\n"), 0700); err != nil {
t.Fatalf("write orphaned runtime: %v", err)
}
err := fixture.plugin.Install(fixture.config)
if err == nil || !strings.Contains(err.Error(), "cannot be verified") {
t.Fatalf("install error = %v", err)
}
current, readErr := os.ReadFile(fixture.hookPath)
if readErr != nil || string(current) != "orphaned\n" {
t.Fatalf("orphaned runtime = %q, %v", current, readErr)
}
for _, path := range []string{
fixture.configPath, fixture.guardPath, fixture.runtimeConfig, fixture.privateKey,
} {
if _, err := os.Lstat(path); !errors.Is(err, os.ErrNotExist) {
t.Fatalf("unexpected file at %s: %v", path, err)
}
}
}
func TestCopilotInstallRejectsLinkedHomeAndRuntimeDirectories(t *testing.T) {
for _, location := range []string{"home", "runtime"} {
t.Run(location, func(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{})
target := filepath.Join(filepath.Dir(fixture.homeDir), location+"-target")
if err := os.MkdirAll(target, 0700); err != nil {
t.Fatalf("create symlink target: %v", err)
}
linkPath := fixture.copilotHome
if location == "runtime" {
linkPath = fixture.agentDir
if err := os.MkdirAll(filepath.Dir(linkPath), 0700); err != nil {
t.Fatalf("create runtime root: %v", err)
}
}
if err := os.Symlink(target, linkPath); err != nil {
t.Skipf("create directory symlink: %v", err)
}
err := fixture.plugin.Install(fixture.config)
if err == nil || !strings.Contains(err.Error(), "physical directory") {
t.Fatalf("install error = %v", err)
}
})
}
}
func TestCopilotStatusRequiresExactRuntimeSourcesAndPrivateKey(t *testing.T) {
for _, name := range []string{"guard", "audit"} {
t.Run(name, func(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{})
installCopilotFixture(t, fixture)
path := fixture.guardPath
if name == "audit" {
path = fixture.hookPath
}
if err := os.WriteFile(path, []byte("// tampered\n"), 0700); err != nil {
t.Fatalf("tamper %s runtime: %v", name, err)
}
status, err := fixture.plugin.Status()
if err != nil || status.Installed || status.HookScriptExists {
t.Fatalf("tampered %s status = %#v, %v", name, status, err)
}
})
}
fixture := prepareCopilotFixture(t, copilotFixtureOptions{})
installCopilotFixture(t, fixture)
if err := os.WriteFile(fixture.privateKey, []byte("invalid"), 0600); err != nil {
t.Fatalf("corrupt private key: %v", err)
}
if _, err := fixture.plugin.Status(); err == nil ||
!strings.Contains(err.Error(), "canonical 32-byte") {
t.Fatalf("invalid key status error = %v", err)
}
}
func TestCopilotValidatesManagedRuntimeInputsBeforeWrites(t *testing.T) {
for _, testCase := range []struct {
name string
edit func(*copilotFixture)
want string
}{
{"agent name", func(f *copilotFixture) { f.config.AgentName = "codex" }, "requires agent name copilot"},
{"organization", func(f *copilotFixture) { f.config.OrgID = " " }, "organization ID is required"},
{"key ID", func(f *copilotFixture) { f.config.KID = "\t" }, "key ID is required"},
{"token", func(f *copilotFixture) { f.config.Token = " " }, "token must contain"},
{"private key", func(f *copilotFixture) { f.config.PrivateKey = "invalid" }, "canonical 32-byte"},
{"base URL", func(f *copilotFixture) {
f.config.BaseURL = "https://api.elydora.com/path?token=secret"
}, "query parameters"},
{"guard path", func(f *copilotFixture) {
f.config.GuardScriptPath = filepath.Join(f.homeDir, "outside", "guard.js")
}, "managed agent directory"},
{"audit path", func(f *copilotFixture) {
f.config.HookScript = filepath.Join(f.homeDir, "outside", "hook.js")
}, "managed agent directory"},
} {
t.Run(testCase.name, func(t *testing.T) {
fixture := prepareCopilotFixture(t, copilotFixtureOptions{})
testCase.edit(fixture)
err := fixture.plugin.Install(fixture.config)
if err == nil || !strings.Contains(err.Error(), testCase.want) {
t.Fatalf("install error = %v, want %q", err, testCase.want)
}
assertCopilotRuntimeAbsent(t, fixture)
})
}
}