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
133 lines
4.6 KiB
Go
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
|
|
}
|