package builtin import ( "context" "encoding/json" "fmt" "os" "path/filepath" "testing" "git.flytoex.net/yuanwei/flyto-agent/pkg/tools" ) // noProgress is a no-op ProgressFunc for benchmarks. var noProgress tools.ProgressFunc // BenchmarkFileRead_BulkVsScanner benchmarks the text file read path // with fileCache enabled (collectFull=true, bulk io.ReadAll path) // and without cache (scanner path with early break). func BenchmarkFileRead_BulkVsScanner(b *testing.B) { // Generate a 10K-line temp file. dir := b.TempDir() filePath := filepath.Join(dir, "large.txt") f, err := os.Create(filePath) if err != nil { b.Fatal(err) } const totalLines = 10_000 for i := 1; i <= totalLines; i++ { fmt.Fprintf(f, "line %d: some representative content that mimics real source code with variables and expressions\n", i) } f.Close() ctx := context.Background() b.Run("with_cache_bulk_read", func(b *testing.B) { cache := newMockFileCacheForRead() tool := &FileReadTool{fileCache: cache} input, _ := json.Marshal(fileReadInput{FilePath: filePath, Limit: 100}) b.ResetTimer() for b.Loop() { res, err := tool.Execute(ctx, input, noProgress) if err != nil || res.IsError { b.Fatalf("Execute failed: err=%v isError=%v", err, res.IsError) } } }) b.Run("no_cache_scanner", func(b *testing.B) { // No fileCache = scanner path, breaks at limit. tool := &FileReadTool{} input, _ := json.Marshal(fileReadInput{FilePath: filePath, Limit: 100}) b.ResetTimer() for b.Loop() { res, err := tool.Execute(ctx, input, noProgress) if err != nil || res.IsError { b.Fatalf("Execute failed: err=%v isError=%v", err, res.IsError) } } }) b.Run("with_cache_offset", func(b *testing.B) { // offset>0 + cache: collectFull=false, scanner path. cache := newMockFileCacheForRead() tool := &FileReadTool{fileCache: cache} input, _ := json.Marshal(fileReadInput{FilePath: filePath, Offset: 5000, Limit: 100}) b.ResetTimer() for b.Loop() { res, err := tool.Execute(ctx, input, noProgress) if err != nil || res.IsError { b.Fatalf("Execute failed: err=%v isError=%v", err, res.IsError) } } }) }