package integration import ( "database/sql" "fmt" "os" "path/filepath" "reflect" "testing" "github.com/versenilvis/iris/internal/config" ) func TestLoadAtuinEntriesPreservesContext(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "history.db") db, err := sql.Open("sqlite", dbPath) if err != nil { t.Fatal(err) } _, err = db.Exec(`CREATE TABLE history ( command TEXT NOT NULL, cwd TEXT NOT NULL, timestamp INTEGER NOT NULL, exit INTEGER NOT NULL, session TEXT NOT NULL, hostname TEXT NOT NULL, deleted_at INTEGER )`) if err != nil { t.Fatal(err) } rows := []struct { command, cwd, session, hostname string timestamp, exit, deletedAt int }{ {"old command", "/repo", "s1", "host", 10, 0, 0}, {"new\ncommand", "/repo/pkg", "s2", "host", 30, 1, 0}, {"deleted command", "/repo", "s3", "host", 40, 0, 99}, } for _, row := range rows { var deletedAt any if row.deletedAt != 0 { deletedAt = row.deletedAt } _, err = db.Exec( "INSERT INTO history VALUES (?, ?, ?, ?, ?, ?, ?)", row.command, row.cwd, row.timestamp, row.exit, row.session, row.hostname, deletedAt, ) if err != nil { t.Fatal(err) } } if err := db.Close(); err != nil { t.Fatal(err) } originalConfig := config.Get() cfg := config.DefaultConfig() cfg.Core.AtuinDBPath = dbPath config.Init(cfg) t.Cleanup(func() { config.Init(originalConfig) }) entries, err := loadAtuinEntries() if err != nil { t.Fatalf("load Atuin entries: %v", err) } if len(entries) != 2 { t.Fatalf("expected two active entries, got %d", len(entries)) } if entries[0].Command != "new command" || entries[0].CWD != "/repo/pkg" || entries[0].Exit != 1 { t.Fatalf("unexpected newest entry: %#v", entries[0]) } if entries[1].Command != "old command" || entries[1].Session != "s1" { t.Fatalf("unexpected oldest entry: %#v", entries[1]) } } func TestApplyAtuinScope(t *testing.T) { repo := t.TempDir() cwd := filepath.Join(repo, "internal", "pkg") if err := os.MkdirAll(filepath.Join(repo, ".git"), 0755); err != nil { t.Fatal(err) } if err := os.MkdirAll(cwd, 0755); err != nil { t.Fatal(err) } originalConfig := config.Get() originalEntries := atuinEntries t.Cleanup(func() { config.Init(originalConfig) atuinEntries = originalEntries }) cfg := config.DefaultConfig() cfg.Core.Atuin = 1 config.Init(cfg) atuinEntries = []atuinEntry{ {Command: "git status", CWD: cwd, Timestamp: 50}, {Command: "git pull", CWD: repo, Timestamp: 40}, {Command: "git status", CWD: cwd, Timestamp: 30}, {Command: "git push", CWD: filepath.Join(t.TempDir(), "other"), Timestamp: 20}, {Command: "git unknown", CWD: "unknown", Timestamp: 10}, } global := []HistResult{ {Cmd: "git push", Source: "atuin"}, {Cmd: "git pull", Source: "atuin"}, {Cmd: "git status", Source: "atuin"}, } tests := []struct { scope string want []string }{ {"global", []string{"git push", "git pull", "git status"}}, {"directory", []string{"git status"}}, {"workspace", []string{"git status", "git pull"}}, {"hybrid", []string{"git status", "git pull", "git push"}}, } for _, tt := range tests { t.Run(tt.scope, func(t *testing.T) { cfg.History.Scope = tt.scope got := resultCommands(applyAtuinScope(global, "g", map[string]string{"g": "git"}, cwd)) if !reflect.DeepEqual(got, tt.want) { t.Fatalf("scope %s: got %v, want %v", tt.scope, got, tt.want) } }) } cfg.History.Scope = "hybrid" if got := resultCommands(applyAtuinScope(global, "", nil, cwd)); !reflect.DeepEqual(got, resultCommands(global)) { t.Fatalf("empty query must stay global: got %v", got) } } func TestWorkspaceScopeOutsideGitUsesDirectory(t *testing.T) { cwd := t.TempDir() originalConfig := config.Get() originalEntries := atuinEntries t.Cleanup(func() { config.Init(originalConfig) atuinEntries = originalEntries }) cfg := config.DefaultConfig() cfg.Core.Atuin = 1 cfg.History.Scope = "workspace" config.Init(cfg) atuinEntries = []atuinEntry{ {Command: "make local", CWD: cwd}, {Command: "make elsewhere", CWD: t.TempDir()}, } got := resultCommands(applyAtuinScope(nil, "make", nil, cwd)) if !reflect.DeepEqual(got, []string{"make local"}) { t.Fatalf("got %v, want directory-only result", got) } } func BenchmarkContextualAtuinCommands(b *testing.B) { repo := b.TempDir() cwd := filepath.Join(repo, "internal", "pkg") if err := os.MkdirAll(filepath.Join(repo, ".git"), 0755); err != nil { b.Fatal(err) } if err := os.MkdirAll(cwd, 0755); err != nil { b.Fatal(err) } entries := make([]atuinEntry, 10000) for i := range entries { entryCWD := repo if i%3 == 0 { entryCWD = cwd } entries[i] = atuinEntry{Command: fmt.Sprintf("command %d", i), CWD: entryCWD} } b.ResetTimer() for range b.N { contextualAtuinCommands(entries, cwd) } } func BenchmarkApplyAtuinScope(b *testing.B) { repo := b.TempDir() cwd := filepath.Join(repo, "internal", "pkg") if err := os.MkdirAll(filepath.Join(repo, ".git"), 0755); err != nil { b.Fatal(err) } if err := os.MkdirAll(cwd, 0755); err != nil { b.Fatal(err) } originalConfig := config.Get() originalEntries := atuinEntries b.Cleanup(func() { config.Init(originalConfig) atuinEntries = originalEntries }) cfg := config.DefaultConfig() cfg.Core.Atuin = 1 cfg.History.Scope = "hybrid" config.Init(cfg) atuinEntries = make([]atuinEntry, 10000) global := make([]HistResult, 10000) for i := range atuinEntries { entryCWD := repo if i%3 == 0 { entryCWD = cwd } command := fmt.Sprintf("command %d", i) atuinEntries[i] = atuinEntry{Command: command, CWD: entryCWD} global[i] = HistResult{Cmd: command, Source: "atuin"} } b.ResetTimer() for range b.N { applyAtuinScope(global, "command 999", nil, cwd) } } func resultCommands(results []HistResult) []string { commands := make([]string, len(results)) for i, result := range results { commands[i] = result.Cmd } return commands }