mirror of
https://github.com/ollama/ollama.git
synced 2026-07-06 07:41:05 +00:00
128 lines
3.6 KiB
Go
128 lines
3.6 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/ollama/ollama/agent"
|
|
)
|
|
|
|
func TestBashReportsFinalWorkingDir(t *testing.T) {
|
|
root := t.TempDir()
|
|
subdir := filepath.Join(root, "sub")
|
|
if err := os.Mkdir(subdir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
result, err := NewBash().Execute(context.Background(), agent.ToolContext{WorkingDir: root}, map[string]any{
|
|
"command": shellTestCommand("cd sub && pwd", "Set-Location sub; Get-Location"),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wantDir, err := filepath.EvalSymlinks(subdir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.WorkingDir != wantDir {
|
|
t.Fatalf("working dir = %q, want %q", result.WorkingDir, wantDir)
|
|
}
|
|
if !strings.Contains(result.Content, "sub") {
|
|
t.Fatalf("content = %q, want pwd output", result.Content)
|
|
}
|
|
}
|
|
|
|
func TestBashBoundsOutputWhileRunning(t *testing.T) {
|
|
result, err := NewBash().Execute(context.Background(), agent.ToolContext{WorkingDir: t.TempDir()}, map[string]any{
|
|
"command": shellTestCommand("yes x | head -c 70000", "[Console]::Out.Write(('x' * 70000))"),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(result.Content, "[stdout truncated: omitted ~") || !strings.Contains(result.Content, " tokens]") {
|
|
t.Fatalf("content = %q, want stdout truncation marker", result.Content)
|
|
}
|
|
if count, want := strings.Count(result.Content, "x"), shellTestCapturedXCount(); count != want {
|
|
t.Fatalf("captured x count = %d, want %d", count, want)
|
|
}
|
|
if len(result.Content) > maxBashOutputBytes+200 {
|
|
t.Fatalf("content length = %d, want bounded output", len(result.Content))
|
|
}
|
|
}
|
|
|
|
func TestBashReportsCanceledCommand(t *testing.T) {
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
cancel()
|
|
|
|
result, err := NewBash().Execute(ctx, agent.ToolContext{WorkingDir: t.TempDir()}, map[string]any{
|
|
"command": shellTestCommand("sleep 10", "Start-Sleep -Seconds 10"),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(result.Content, "Error: command was canceled") {
|
|
t.Fatalf("content = %q, want canceled message", result.Content)
|
|
}
|
|
if strings.Contains(result.Content, "Exit code: -1") {
|
|
t.Fatalf("content = %q, should not mask cancellation as exit code", result.Content)
|
|
}
|
|
}
|
|
|
|
func shellTestCommand(unix, windows string) string {
|
|
if runtime.GOOS == "windows" {
|
|
return windows
|
|
}
|
|
return unix
|
|
}
|
|
|
|
func shellTestCapturedXCount() int {
|
|
if runtime.GOOS == "windows" {
|
|
return maxBashOutputBytes
|
|
}
|
|
return maxBashOutputBytes / 2
|
|
}
|
|
|
|
func TestReadFinalWorkingDirRejectsInvalidPaths(t *testing.T) {
|
|
dir := t.TempDir()
|
|
cwdFile := filepath.Join(dir, "cwd")
|
|
notDir := filepath.Join(dir, "file.txt")
|
|
if err := os.WriteFile(notDir, []byte("not a dir"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if err := os.WriteFile(cwdFile, []byte(notDir+"\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := readFinalWorkingDir(cwdFile); got != "" {
|
|
t.Fatalf("regular file cwd = %q, want empty", got)
|
|
}
|
|
|
|
if err := os.WriteFile(cwdFile, []byte(filepath.Join(dir, "missing")+"\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := readFinalWorkingDir(cwdFile); got != "" {
|
|
t.Fatalf("missing cwd = %q, want empty", got)
|
|
}
|
|
|
|
if err := os.WriteFile(cwdFile, []byte(dir+"\n"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := readFinalWorkingDir(cwdFile); got != dir {
|
|
t.Fatalf("directory cwd = %q, want %q", got, dir)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeBashWorkingDirWindowsDriveLetter(t *testing.T) {
|
|
if runtime.GOOS != "windows" {
|
|
t.Skip("windows path normalization")
|
|
}
|
|
got := normalizeBashWorkingDir("/c/Users/jdoe/project")
|
|
want := filepath.Clean(`C:\Users\jdoe\project`)
|
|
if got != want {
|
|
t.Fatalf("working dir = %q, want %q", got, want)
|
|
}
|
|
}
|