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

133 lines
4.6 KiB
Go

// Package fixtures detects test-fixture files and surfaces them as
// KindFixture nodes so agents can answer "what fixtures does this
// repo have" or "is this golden file still referenced" with a graph
// query rather than a directory walk.
//
// Scope (v1): per-file path-based detection. A file qualifies as a
// fixture when its path contains a `testdata/` segment — Go's
// well-known convention for test data, also adopted by many other
// ecosystems (Python, Rust, JS). The reference edge from test
// functions to fixtures (`EdgeReferences` per the broader coverage
// spec) is a v2 follow-up; today the fixture node lands without
// an inbound link, which still serves enumeration and cleanup
// queries.
package fixtures
import (
"path/filepath"
"strings"
"github.com/zzet/gortex/internal/graph"
)
// IsFixturePath reports whether a repo-relative file path lives
// under a `testdata/` directory. Forward-slash and back-slash
// separators are both accepted so Windows-indexed paths produce the
// same result as POSIX-indexed ones. Path-only — does not consult
// the filesystem.
func IsFixturePath(filePath string) bool {
p := filepath.ToSlash(filePath)
if p == "" {
return false
}
// Match `testdata` as a whole segment, not as a prefix or
// substring of a longer name (e.g. `mytestdata/`). The two
// patterns are: leading `testdata/` and any `/testdata/` mid-
// path.
if strings.HasPrefix(p, "testdata/") {
return true
}
return strings.Contains(p, "/testdata/")
}
// BuildGraphArtifacts emits a KindFixture node for the given file.
// Returns nil when the path doesn't qualify so the caller can
// unconditionally invoke this without an explicit IsFixturePath
// guard at every call site.
//
// filePath is the unprefixed repo-relative path; applyRepoPrefix
// downstream handles multi-repo namespacing. The fixture node
// shares the same ID as the file node so a single graph query can
// scope to fixtures via kind, and the existing file-shaped node
// from the language extractor (when present) carries its own
// outgoing edges.
//
// We deliberately do not emit a separate node ID — the fixture is
// the file. Keeping a single ID keeps cross-referencing simple
// (any edge that lands on the file path also lands on the fixture
// classification) and avoids the de-dup gymnastics that emitting a
// twin synthetic ID would require.
func BuildGraphArtifacts(filePath, language string) []*graph.Node {
if !IsFixturePath(filePath) {
return nil
}
filePath = filepath.ToSlash(filePath)
return []*graph.Node{{
ID: filePath,
Kind: graph.KindFixture,
Name: filepath.Base(filePath),
FilePath: filePath,
Language: language,
Meta: map[string]any{
"fixture": true,
},
}}
}
// TestContractSource reports the test-fixture category of the given
// path, or "" if the path is production code. Used by the contracts
// pipeline to tag — not drop — contracts emitted from synthetic
// fixtures so the dashboard can filter them out by default while
// still keeping them in the graph for drift checks (e.g. a test
// pinned to an old API contract that production has since changed).
//
// Categories:
// - "testdata" — paths under testdata/ (Go convention)
// - "bench_fixtures" — paths under bench/fixtures/ (gortex bench corpus)
// - "js_fixtures" — paths under __fixtures__/ (TS/JS convention)
//
// The path may be repo-prefixed (e.g. "gortex/bench/fixtures/...");
// we match the segment regardless of leading prefix. Path-only — does
// not consult the filesystem.
func TestContractSource(filePath string) string {
if IsFixturePath(filePath) {
return "testdata"
}
p := filepath.ToSlash(filePath)
if p == "" {
return ""
}
for _, c := range []struct {
seg, label string
}{
{"bench/fixtures/", "bench_fixtures"},
{"__fixtures__/", "js_fixtures"},
} {
if strings.HasPrefix(p, c.seg) || strings.Contains(p, "/"+c.seg) {
return c.label
}
}
return ""
}
// ReclassifyFileToFixture rewrites an existing KindFile node to
// KindFixture when its path qualifies. Used by the indexer's
// per-file coverage step so the language extractor's emitted file
// node is upgraded in place rather than producing two nodes that
// share an ID. Returns true when reclassification fired so callers
// can skip BuildGraphArtifacts for the same path.
func ReclassifyFileToFixture(node *graph.Node) bool {
if node == nil || node.Kind != graph.KindFile {
return false
}
if !IsFixturePath(node.FilePath) {
return false
}
node.Kind = graph.KindFixture
if node.Meta == nil {
node.Meta = map[string]any{}
}
node.Meta["fixture"] = true
return true
}