Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

231 lines
6.5 KiB
Go

package scip
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"github.com/zzet/gortex/internal/graph"
)
func TestSCIPProtobufRoundTrip(t *testing.T) {
index := &SCIPIndex{
Documents: []SCIPDocument{
{
RelativePath: "main.go",
Occurrences: []SCIPOccurrence{
{
Range: []int32{9, 5, 9, 9}, // line 10 (0-indexed=9), col 5-9
Symbol: "scip-go gomod example.com v1.0.0 main.Foo().",
SymbolRoles: 1, // Definition
},
{
Range: []int32{14, 2, 14, 5},
Symbol: "scip-go gomod example.com v1.0.0 main.Bar().",
SymbolRoles: 0, // Reference
},
},
Symbols: []SCIPSymbolInfo{
{
Symbol: "scip-go gomod example.com v1.0.0 main.Foo().",
Documentation: []string{"func Foo() error"},
},
},
},
},
}
// Encode to protobuf.
data := encodeSCIPForTesting(index)
require.NotEmpty(t, data)
// Decode back.
decoded, err := decodeSCIPProtobuf(data)
require.NoError(t, err)
require.Len(t, decoded.Documents, 1)
doc := decoded.Documents[0]
assert.Equal(t, "main.go", doc.RelativePath)
require.Len(t, doc.Occurrences, 2)
// Check definition.
assert.Equal(t, int32(9), doc.Occurrences[0].Range[0])
assert.True(t, doc.Occurrences[0].IsDefinition())
assert.Equal(t, 10, doc.Occurrences[0].StartLine()) // 0-indexed → 1-indexed
// Check reference.
assert.False(t, doc.Occurrences[1].IsDefinition())
// Check symbol info.
require.Len(t, doc.Symbols, 1)
assert.Contains(t, doc.Symbols[0].Documentation[0], "func Foo()")
}
func TestSCIPJSONParsing(t *testing.T) {
tmpDir := t.TempDir()
jsonFile := filepath.Join(tmpDir, "index.scip")
jsonData := `{
"documents": [
{
"relative_path": "pkg/handler.go",
"occurrences": [
{"range": [4, 5, 4, 11], "symbol": "pkg.Handle()", "symbol_roles": 1},
{"range": [10, 2, 10, 8], "symbol": "pkg.Handle()", "symbol_roles": 0}
],
"symbols": [
{
"symbol": "pkg.Handle()",
"documentation": ["func Handle(w http.ResponseWriter, r *http.Request)"],
"relationships": [
{"symbol": "http.Handler", "is_implementation": true}
]
}
]
}
]
}`
require.NoError(t, os.WriteFile(jsonFile, []byte(jsonData), 0644))
index, err := ParseSCIPFile(jsonFile)
require.NoError(t, err)
require.Len(t, index.Documents, 1)
doc := index.Documents[0]
assert.Equal(t, "pkg/handler.go", doc.RelativePath)
require.Len(t, doc.Occurrences, 2)
require.Len(t, doc.Symbols, 1)
require.Len(t, doc.Symbols[0].Relationships, 1)
assert.True(t, doc.Symbols[0].Relationships[0].IsImplementation)
}
func TestEnrichFromIndex(t *testing.T) {
logger := zap.NewNop()
p := NewProvider("scip-go", nil, []string{"go"}, 120, logger)
g := graph.New()
g.AddNode(&graph.Node{
ID: "main.go::Foo", Kind: graph.KindFunction, Name: "Foo",
FilePath: "main.go", StartLine: 10, EndLine: 20, Language: "go",
})
g.AddNode(&graph.Node{
ID: "main.go::Bar", Kind: graph.KindFunction, Name: "Bar",
FilePath: "main.go", StartLine: 22, EndLine: 30, Language: "go",
})
// Add an INFERRED edge.
g.AddEdge(&graph.Edge{
From: "main.go::Bar", To: "main.go::Foo", Kind: graph.EdgeCalls,
Confidence: 0.7, ConfidenceLabel: "INFERRED",
})
// Create a SCIP index that confirms the call.
index := &SCIPIndex{
Documents: []SCIPDocument{
{
RelativePath: "main.go",
Occurrences: []SCIPOccurrence{
{
Range: []int32{9, 5, 9, 8}, // line 10 (Foo definition)
Symbol: "main.Foo()",
SymbolRoles: 1, // Definition
},
{
Range: []int32{21, 5, 21, 8}, // line 22 (Bar definition)
Symbol: "main.Bar()",
SymbolRoles: 1, // Definition
},
{
Range: []int32{24, 2, 24, 5}, // line 25 (call to Foo from Bar)
Symbol: "main.Foo()",
SymbolRoles: 0, // Reference
},
},
Symbols: []SCIPSymbolInfo{
{
Symbol: "main.Foo()",
Documentation: []string{"func Foo() error"},
},
},
},
},
}
result := p.enrichFromIndex(g, index, "/tmp/repo")
assert.Greater(t, result.SymbolsCovered, 0)
assert.Greater(t, result.EdgesConfirmed, 0)
// Verify the edge was confirmed.
edges := g.GetOutEdges("main.go::Bar")
require.NotEmpty(t, edges)
for _, e := range edges {
if e.To == "main.go::Foo" && e.Kind == graph.EdgeCalls {
assert.Equal(t, 1.0, e.Confidence)
assert.Equal(t, "EXTRACTED", e.ConfidenceLabel)
}
}
}
// TestEnrichFromIndex_DefinitionsOnly verifies the C# / .NET coverage
// helper fast path: definitions are mapped (coverage counted) but the
// reference-edge pass is skipped, so no edge is confirmed or added.
func TestEnrichFromIndex_DefinitionsOnly(t *testing.T) {
p := NewProvider("scip-dotnet", nil, []string{"csharp"}, 120, zap.NewNop()).
WithDefinitionsOnly()
g := graph.New()
g.AddNode(&graph.Node{
ID: "M.cs::Foo", Kind: graph.KindMethod, Name: "Foo",
FilePath: "M.cs", StartLine: 10, EndLine: 20, Language: "csharp",
})
g.AddNode(&graph.Node{
ID: "M.cs::Bar", Kind: graph.KindMethod, Name: "Bar",
FilePath: "M.cs", StartLine: 22, EndLine: 30, Language: "csharp",
})
g.AddEdge(&graph.Edge{
From: "M.cs::Bar", To: "M.cs::Foo", Kind: graph.EdgeCalls,
Confidence: 0.7, ConfidenceLabel: "INFERRED",
})
index := &SCIPIndex{Documents: []SCIPDocument{{
RelativePath: "M.cs",
Occurrences: []SCIPOccurrence{
{Range: []int32{9, 5, 9, 8}, Symbol: "M.Foo()", SymbolRoles: 1},
{Range: []int32{21, 5, 21, 8}, Symbol: "M.Bar()", SymbolRoles: 1},
{Range: []int32{24, 2, 24, 5}, Symbol: "M.Foo()", SymbolRoles: 0}, // reference
},
}}}
result := p.enrichFromIndex(g, index, "/tmp/repo")
assert.Greater(t, result.SymbolsCovered, 0, "definitions must still be mapped")
assert.Equal(t, 0, result.EdgesConfirmed, "reference pass must be skipped")
assert.Equal(t, 0, result.EdgesAdded, "reference pass must be skipped")
edges := g.GetOutEdges("M.cs::Bar")
require.NotEmpty(t, edges)
assert.Equal(t, 0.7, edges[0].Confidence, "INFERRED edge must stay unconfirmed")
}
func TestExtractSymbolName(t *testing.T) {
tests := []struct {
symbol string
want string
}{
{"scip-go gomod github.com/foo/bar v1.0.0 pkg.Foo().", "Foo"},
{"scip-go gomod github.com/foo/bar v1.0.0 internal/graph/Graph.AddNode().", "AddNode"},
{"scip-go gomod github.com/foo/bar v1.0.0 internal/graph/Node#Kind.", "Kind"},
{"", ""},
}
for _, tt := range tests {
got := extractSymbolName(tt.symbol)
assert.Equal(t, tt.want, got, "for symbol %q", tt.symbol)
}
}