mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-06 02:34:09 +08:00
- Move all source files to internal/{app,backend,config,executor,logger,parser,utils}
- Integrate third-party libraries: zerolog, goccy/go-json, gopsutil, cobra/viper
- Add comprehensive unit tests for utils package (94.3% coverage)
- Add performance benchmarks for string operations
- Fix error display: cleanup warnings no longer pollute Recent Errors
- Add GitHub Actions CI workflow
- Add Makefile for build automation
- Add README documentation
Generated with SWE-Agent.ai
Co-Authored-By: SWE-Agent.ai <noreply@swe-agent.ai>
187 lines
5.0 KiB
Go
187 lines
5.0 KiB
Go
package executor
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestWrapTaskWithAgentPrompt(t *testing.T) {
|
|
got := WrapTaskWithAgentPrompt("P", "do")
|
|
want := "<agent-prompt>\nP\n</agent-prompt>\n\ndo"
|
|
if got != want {
|
|
t.Fatalf("wrapTaskWithAgentPrompt mismatch:\n got=%q\nwant=%q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_EmptyPath(t *testing.T) {
|
|
for _, allowOutside := range []bool{false, true} {
|
|
got, err := ReadAgentPromptFile(" ", allowOutside)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error (allowOutside=%v): %v", allowOutside, err)
|
|
}
|
|
if got != "" {
|
|
t.Fatalf("expected empty result (allowOutside=%v), got %q", allowOutside, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_ExplicitAbsolutePath(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "prompt.md")
|
|
if err := os.WriteFile(path, []byte("LINE1\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
got, err := ReadAgentPromptFile(path, true)
|
|
if err != nil {
|
|
t.Fatalf("readAgentPromptFile error: %v", err)
|
|
}
|
|
if got != "LINE1" {
|
|
t.Fatalf("got %q, want %q", got, "LINE1")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_ExplicitTildeExpansion(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
path := filepath.Join(home, "prompt.md")
|
|
if err := os.WriteFile(path, []byte("P\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
got, err := ReadAgentPromptFile("~/prompt.md", true)
|
|
if err != nil {
|
|
t.Fatalf("readAgentPromptFile error: %v", err)
|
|
}
|
|
if got != "P" {
|
|
t.Fatalf("got %q, want %q", got, "P")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_RestrictedAllowsClaudeDir(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
claudeDir := filepath.Join(home, ".claude")
|
|
if err := os.MkdirAll(claudeDir, 0o755); err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
path := filepath.Join(claudeDir, "prompt.md")
|
|
if err := os.WriteFile(path, []byte("OK\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
got, err := ReadAgentPromptFile("~/.claude/prompt.md", false)
|
|
if err != nil {
|
|
t.Fatalf("readAgentPromptFile error: %v", err)
|
|
}
|
|
if got != "OK" {
|
|
t.Fatalf("got %q, want %q", got, "OK")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_RestrictedAllowsCodeagentAgentsDir(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
agentDir := filepath.Join(home, ".codeagent", "agents")
|
|
if err := os.MkdirAll(agentDir, 0o755); err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
path := filepath.Join(agentDir, "sarsh.md")
|
|
if err := os.WriteFile(path, []byte("OK\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
got, err := ReadAgentPromptFile("~/.codeagent/agents/sarsh.md", false)
|
|
if err != nil {
|
|
t.Fatalf("readAgentPromptFile error: %v", err)
|
|
}
|
|
if got != "OK" {
|
|
t.Fatalf("got %q, want %q", got, "OK")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_RestrictedRejectsOutsideClaudeDir(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
path := filepath.Join(home, "prompt.md")
|
|
if err := os.WriteFile(path, []byte("NO\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
if _, err := ReadAgentPromptFile("~/prompt.md", false); err == nil {
|
|
t.Fatalf("expected error for prompt file outside ~/.claude, got nil")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_RestrictedRejectsTraversal(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
path := filepath.Join(home, "secret.md")
|
|
if err := os.WriteFile(path, []byte("SECRET\n"), 0o644); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
|
|
if _, err := ReadAgentPromptFile("~/.claude/../secret.md", false); err == nil {
|
|
t.Fatalf("expected traversal to be rejected, got nil")
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_NotFound(t *testing.T) {
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
claudeDir := filepath.Join(home, ".claude")
|
|
if err := os.MkdirAll(claudeDir, 0o755); err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
|
|
_, err := ReadAgentPromptFile("~/.claude/missing.md", false)
|
|
if err == nil || !os.IsNotExist(err) {
|
|
t.Fatalf("expected not-exist error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestReadAgentPromptFile_PermissionDenied(t *testing.T) {
|
|
if runtime.GOOS == "windows" {
|
|
t.Skip("chmod-based permission test is not reliable on Windows")
|
|
}
|
|
|
|
home := t.TempDir()
|
|
t.Setenv("HOME", home)
|
|
t.Setenv("USERPROFILE", home)
|
|
|
|
claudeDir := filepath.Join(home, ".claude")
|
|
if err := os.MkdirAll(claudeDir, 0o755); err != nil {
|
|
t.Fatalf("MkdirAll: %v", err)
|
|
}
|
|
path := filepath.Join(claudeDir, "private.md")
|
|
if err := os.WriteFile(path, []byte("PRIVATE\n"), 0o600); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
if err := os.Chmod(path, 0o000); err != nil {
|
|
t.Fatalf("Chmod: %v", err)
|
|
}
|
|
|
|
_, err := ReadAgentPromptFile("~/.claude/private.md", false)
|
|
if err == nil {
|
|
t.Fatalf("expected permission error, got nil")
|
|
}
|
|
if !os.IsPermission(err) && !strings.Contains(strings.ToLower(err.Error()), "permission") {
|
|
t.Fatalf("expected permission denied, got: %v", err)
|
|
}
|
|
}
|