package tools import ( "context" "os" "path/filepath" "strings" "testing" ) func readIn(t *testing.T, input string, files map[string]string) (string, error) { t.Helper() dir := t.TempDir() for name, content := range files { p := filepath.Join(dir, name) if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(p, []byte(content), 0o644); err != nil { t.Fatal(err) } } reg := NewRegistry() for _, tl := range BuiltinIn(dir, NewFence(), nil) { if err := reg.Register(tl); err != nil { t.Fatal(err) } } r, _ := reg.Get("read") res, err := r.Run(context.Background(), input) return res.Text, err } // TestReadSmallFileUnchanged:不分页的小文件保持原样,不加头尾。 func TestReadSmallFileUnchanged(t *testing.T) { got, err := readIn(t, `{"path":"f.txt"}`, map[string]string{"f.txt": "a\nb\nc\n"}) if err != nil { t.Fatal(err) } if got != "a\nb\nc\n" { t.Fatalf("got %q", got) } } func TestReadOffsetLimit(t *testing.T) { got, err := readIn(t, `{"path":"f.txt","offset":2,"limit":2}`, map[string]string{"f.txt": "l1\nl2\nl3\nl4\nl5\n"}) if err != nil { t.Fatal(err) } if !strings.Contains(got, "lines 2-3 of 5") || !strings.Contains(got, "l2\nl3") { t.Fatalf("got %q", got) } if !strings.Contains(got, "continue with offset: 4") { t.Fatalf("missing continuation: %q", got) } if strings.Contains(got, "l1") || strings.Contains(got, "l4") { t.Fatalf("paging leaked other lines: %q", got) } } func TestReadBeyondEOF(t *testing.T) { got, err := readIn(t, `{"path":"f.txt","offset":99}`, map[string]string{"f.txt": "a\nb\n"}) if err != nil { t.Fatal(err) } if !strings.Contains(got, "beyond EOF") { t.Fatalf("got %q", got) } } func TestReadDirectoryListing(t *testing.T) { got, err := readIn(t, `{"path":".","offset":2,"limit":1}`, map[string]string{ "a.txt": "x", "sub/b.go": "y", }) if err != nil { t.Fatal(err) } if !strings.Contains(got, "entries 2-2 of 2") || !strings.Contains(got, "sub/") { t.Fatalf("got %q", got) } if strings.Contains(got, "a.txt") { t.Fatalf("paging leaked other entries: %q", got) } } func TestReadRejectsBinary(t *testing.T) { dir := t.TempDir() p := filepath.Join(dir, "bin") if err := os.WriteFile(p, []byte{'a', 0, 'b'}, 0o644); err != nil { t.Fatal(err) } reg := NewRegistry() for _, tl := range BuiltinIn(dir, NewFence(), nil) { if err := reg.Register(tl); err != nil { t.Fatal(err) } } r, _ := reg.Get("read") if _, err := r.Run(context.Background(), `{"path":"bin"}`); err == nil || !strings.Contains(err.Error(), "binary") { t.Fatalf("want binary error, got %v", err) } }