xdebug-mcp/internal/cachegrind/parser_test.go
thibaud-leclere 47040d50ae feat: add cachegrind parser with gzip support
Two-pass parser resolves forward cfn= references; all cost lines
(including call edges) are accumulated as inclusive costs per function.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 09:41:31 +02:00

81 lines
1.8 KiB
Go

package cachegrind_test
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"forge.lclr.dev/AI/xdebug-mcp/internal/cachegrind"
)
const simpleFixture = `version: 1
creator: test
cmd: index.php
part: 1
positions: line
events: Time_(10ns) Memory_(bytes)
fl=(1) index.php
fn=(1) main
1 2000 1000
cfl=(1)
cfn=(2)
calls=1 0 0
2 1500 700
fl=(1)
fn=(2) query
10 1500 700
cfl=(1)
cfn=(3)
calls=2 0 0
15 500 200
fl=(1)
fn=(3) connect
20 250 100
`
func TestParseSimple(t *testing.T) {
p, err := cachegrind.Parse(strings.NewReader(simpleFixture))
require.NoError(t, err)
assert.Equal(t, "index.php", p.Cmd)
assert.Equal(t, []string{"Time_(10ns)", "Memory_(bytes)"}, p.Events)
assert.Len(t, p.Functions, 3)
main := p.ByName["main"]
require.Len(t, main, 1)
// main costs: self (2000,1000) + call to query (1500,700) = (3500,1700)
assert.Equal(t, []int64{3500, 1700}, main[0].Costs)
assert.Len(t, main[0].Calls, 1)
assert.Equal(t, int64(1), main[0].Calls[0].Count)
assert.Equal(t, "query", main[0].Calls[0].Callee.Name)
query := p.ByName["query"]
require.Len(t, query, 1)
assert.Equal(t, []int64{2000, 900}, query[0].Costs)
assert.Len(t, query[0].CalledBy, 1)
assert.Len(t, query[0].Calls, 1)
assert.Equal(t, int64(2), query[0].Calls[0].Count)
connect := p.ByName["connect"]
require.Len(t, connect, 1)
assert.Equal(t, []int64{250, 100}, connect[0].Costs)
assert.Empty(t, connect[0].Calls)
assert.Len(t, connect[0].CalledBy, 1)
}
func TestParseFile_gzip(t *testing.T) {
path := "/home/leclere/Uppler/apps/uppler1/docker/tmp/xdebug/cachegrind.out.45.gz"
p, err := cachegrind.ParseFile(path)
if err != nil {
t.Skipf("real file unavailable: %v", err)
}
assert.NotEmpty(t, p.Events)
assert.NotEmpty(t, p.Functions)
assert.NotEmpty(t, p.Cmd)
}