Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

159 lines
4.8 KiB
Go

package storesqlite
import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"
)
func TestNormalizeAgentSessionRailSectionDerivesKeyFromPath(t *testing.T) {
t.Parallel()
root := t.TempDir()
canonical := NormalizeProjectPath(root)
aliased := root
if runtime.GOOS == "darwin" {
// On macOS TempDir is often under /var which is a symlink to /private/var.
if evaluated, err := filepath.EvalSymlinks(root); err == nil && evaluated != root {
aliased = root
canonical = evaluated
}
}
section := normalizeAgentSessionRailSection(RailSection{
Kind: RailSectionKindProject,
ProjectPath: aliased,
Key: "project:" + aliased,
})
if section.ProjectPath != canonical {
t.Fatalf("ProjectPath = %q, want %q", section.ProjectPath, canonical)
}
wantKey := RailSectionKeyForProject(canonical)
if section.Key != wantKey {
t.Fatalf("Key = %q, want %q", section.Key, wantKey)
}
if !isValidAgentSessionRailSection(section) {
t.Fatalf("normalized section should be valid: %#v", section)
}
}
func TestNormalizeAgentSessionRailSectionRepairsMismatchedKey(t *testing.T) {
t.Parallel()
root := t.TempDir()
canonical := NormalizeProjectPath(root)
section := normalizeAgentSessionRailSection(RailSection{
Kind: RailSectionKindProject,
ProjectPath: canonical,
Key: "project:/unrelated/path",
})
if section.Key != RailSectionKeyForProject(canonical) {
t.Fatalf("Key = %q, want derived from path", section.Key)
}
}
func TestNormalizeRailSectionKeyAliasesCompareEqual(t *testing.T) {
t.Parallel()
root := t.TempDir()
canonical := NormalizeProjectPath(root)
if canonical == root {
t.Skip("temp dir path is already canonical; no symlink alias to assert")
}
if NormalizeRailSectionKey("project:"+root) != NormalizeRailSectionKey("project:"+canonical) {
t.Fatalf(
"NormalizeRailSectionKey(%q) != NormalizeRailSectionKey(%q)",
root,
canonical,
)
}
}
func TestNormalizeAgentSessionRailSectionClearsConversationProjectBinding(t *testing.T) {
t.Parallel()
section := normalizeAgentSessionRailSection(RailSection{
Kind: RailSectionKindConversations,
ProjectPath: t.TempDir(),
Key: "project:/tmp/x",
})
if section.ProjectPath != "" || section.Key != RailSectionKeyConversations {
t.Fatalf("conversations section = %#v", section)
}
}
func TestClassifyRailSectionUsesCanonicalProjectKey(t *testing.T) {
t.Parallel()
root := t.TempDir()
if err := os.MkdirAll(filepath.Join(root, "pkg"), 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
section := ClassifyRailSection(filepath.Join(root, "pkg"), nil, []string{root})
want := RailSectionKeyForProject(root)
if section.Key != want {
t.Fatalf("ClassifyRailSection key = %q, want %q", section.Key, want)
}
}
func TestRailSectionKeyForProjectUsesWindowsCaseInsensitiveIdentity(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" {
t.Skip("Windows filesystem identity is platform-specific")
}
left := `C:\Users\Demo\Repo`
right := `c:\users\demo\repo`
if RailSectionKeyForProject(left) != RailSectionKeyForProject(right) {
t.Fatalf("Windows project keys differ: %q vs %q", RailSectionKeyForProject(left), RailSectionKeyForProject(right))
}
}
func TestWindowsRailPreservesPOSIXProjectNamespace(t *testing.T) {
t.Parallel()
const projectPath = "/workspace/Snake"
if got := normalizeProjectPathForPlatform(projectPath, "windows"); got != projectPath {
t.Fatalf("NormalizeProjectPath = %q, want %q", got, projectPath)
}
if got := railIdentityPathForPlatform(projectPath, "windows"); got != projectPath {
t.Fatalf("rail identity = %q, want case-sensitive %q", got, projectPath)
}
if !isProjectPathWithinForPlatform(projectPath, projectPath+"/src", "windows") {
t.Fatalf("POSIX child should remain within %q on Windows", projectPath)
}
if isProjectPathWithinForPlatform(projectPath, "/workspace/snake/src", "windows") {
t.Fatalf("POSIX project identity should remain case-sensitive on Windows")
}
}
func TestRailSectionKeyForProjectPreservesPOSIXIdentityOnWindows(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" {
t.Skip("Windows path normalization is platform-specific")
}
const projectPath = "/workspace/Snake"
if got, want := RailSectionKeyForProject(projectPath), "project:"+projectPath; got != want {
t.Fatalf("RailSectionKeyForProject = %q, want %q", got, want)
}
}
func TestIsProjectPathWithinUsesWindowsCaseInsensitiveIdentity(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" {
t.Skip("Windows filesystem identity is platform-specific")
}
root := filepath.Join(t.TempDir(), "Project")
child := filepath.Join(root, "Packages", "App")
if err := os.MkdirAll(child, 0o755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if !IsProjectPathWithin(strings.ToUpper(root), strings.ToLower(child)) {
t.Fatalf("Windows path identity should recognize %q as within %q", child, root)
}
}