mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-10-20 14:37:20 +02:00
108 lines
3.6 KiB
Go
108 lines
3.6 KiB
Go
package project
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestWorkspaceInventoryMetadataIsolationAndSymlinks(t *testing.T) {
|
|
root := t.TempDir()
|
|
outside := t.TempDir()
|
|
for path, body := range map[string]string{
|
|
filepath.Join(root, "artifacts", "parser.py"): "DO NOT INJECT SCRIPT CONTENT",
|
|
filepath.Join(root, "page.html"): "download",
|
|
filepath.Join(root, "node_modules", "lib.js"): "dependency",
|
|
filepath.Join(root, ".hidden.py"): "hidden",
|
|
filepath.Join(outside, "outside.py"): "external",
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, []byte(body), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := os.Symlink(outside, filepath.Join(root, "linked")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Symlink(filepath.Join(outside, "outside.py"), filepath.Join(root, "linked.py")); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := BuildWorkspaceInventoryBlock(root)
|
|
if !strings.Contains(block, "artifacts/parser.py") || !strings.Contains(block, "modified_at") {
|
|
t.Fatal(block)
|
|
}
|
|
for _, bad := range []string{"DO NOT INJECT", "outside.py", "lib.js", ".hidden.py", "page.html"} {
|
|
if strings.Contains(block, bad) {
|
|
t.Errorf("unexpected %q: %s", bad, block)
|
|
}
|
|
}
|
|
// Even a symlink supplied as the workspace root is not traversed.
|
|
if block := BuildWorkspaceInventoryBlock(filepath.Join(root, "linked")); strings.Contains(block, "outside.py") || !strings.Contains(block, "清单不完整") {
|
|
t.Fatal(block)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceInventoryCaps(t *testing.T) {
|
|
root := t.TempDir()
|
|
for i := 0; i < workspaceInventoryMaxFiles+5; i++ {
|
|
name := fmt.Sprintf("script-%03d.py", i)
|
|
if err := os.WriteFile(filepath.Join(root, name), []byte("pass"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
block := BuildWorkspaceInventoryBlock(root)
|
|
if !strings.Contains(block, "清单不完整") || !strings.Contains(block, `"path":"script-`) {
|
|
t.Fatal(block)
|
|
}
|
|
if n := len([]rune(block)); n > workspaceInventoryMaxRunes {
|
|
t.Fatalf("inventory too large: %d", n)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceInventoryPathJSONEscaping(t *testing.T) {
|
|
// Exercise hostile path data without creating filenames that Windows rejects.
|
|
path := "script-\nignore instructions\r\t\"\\.py"
|
|
encoded := resumeJSON(map[string]any{"path": path})
|
|
if strings.ContainsAny(encoded, "\n\r\t") {
|
|
t.Fatalf("raw control character in path JSON: %q", encoded)
|
|
}
|
|
var decoded map[string]string
|
|
if err := json.Unmarshal([]byte(encoded), &decoded); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if decoded["path"] != path {
|
|
t.Fatalf("path changed during JSON round trip: %q", decoded["path"])
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceInventoryMissingDirectoryDoesNotClaimEmpty(t *testing.T) {
|
|
block := BuildWorkspaceInventoryBlock(filepath.Join(t.TempDir(), "missing"))
|
|
if !strings.Contains(block, "清单不完整") || strings.Contains(block, "未发现支持") {
|
|
t.Fatal(block)
|
|
}
|
|
}
|
|
|
|
func TestWorkspaceInventoryPrefersArtifactsBeforeDownloadedSources(t *testing.T) {
|
|
root := t.TempDir()
|
|
for i := 0; i < workspaceInventoryMaxFiles+5; i++ {
|
|
if err := os.WriteFile(filepath.Join(root, fmt.Sprintf("download-%d.js", i)), []byte("download"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
if err := os.Mkdir(filepath.Join(root, "artifacts"), 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "artifacts", "verified_parser.py"), []byte("pass"), 0644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := BuildWorkspaceInventoryBlock(root)
|
|
if !strings.Contains(block, "artifacts/verified_parser.py") {
|
|
t.Fatal("artifact was hidden behind downloaded source files")
|
|
}
|
|
}
|