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
135 lines
3.7 KiB
Go
135 lines
3.7 KiB
Go
package review
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/zzet/gortex/internal/analysis"
|
|
"github.com/zzet/gortex/internal/graph"
|
|
)
|
|
|
|
// TestClassifyChange_Classes drives every change class through ClassifyChange,
|
|
// asserting the precedence (test/config structural, then fix>refactor>feature on
|
|
// the hunk).
|
|
func TestClassifyChange_Classes(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
sym analysis.ChangedSymbol
|
|
hunk string
|
|
want string
|
|
}{
|
|
{
|
|
name: "test file wins over hunk content",
|
|
sym: analysis.ChangedSymbol{ID: "a_test.go::TestFoo", Name: "TestFoo", Kind: "function", FilePath: "a_test.go"},
|
|
hunk: "+func TestFoo() {}\n",
|
|
want: ClassTest,
|
|
},
|
|
{
|
|
name: "test symbol name wins",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::TestBar", Name: "TestBar", Kind: "function", FilePath: "a.go"},
|
|
hunk: "+\tx := 1\n",
|
|
want: ClassTest,
|
|
},
|
|
{
|
|
name: "yaml file is config",
|
|
sym: analysis.ChangedSymbol{ID: "deploy.yaml::x", Name: "x", FilePath: "config/deploy.yaml"},
|
|
hunk: "+replicas: 3\n",
|
|
want: ClassConfig,
|
|
},
|
|
{
|
|
name: "constant node kind is config",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::MaxN", Name: "MaxN", Kind: "constant", FilePath: "a.go"},
|
|
hunk: "+const MaxN = 5\n",
|
|
want: ClassConfig,
|
|
},
|
|
{
|
|
name: "added error handling is a fix",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::Load", Name: "Load", Kind: "function", FilePath: "internal/svc/a.go"},
|
|
hunk: "+\tif err != nil {\n+\t\treturn err\n+\t}\n",
|
|
want: ClassFix,
|
|
},
|
|
{
|
|
name: "equal add/remove is a refactor",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::Sum", Name: "Sum", Kind: "function", FilePath: "a.go"},
|
|
hunk: "-\treturn a + b\n+\ttotal := a + b\n",
|
|
want: ClassRefactor,
|
|
},
|
|
{
|
|
name: "net-new lines is a feature",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::NewThing", Name: "NewThing", Kind: "function", FilePath: "a.go"},
|
|
hunk: "+func NewThing() *Thing {\n+\treturn &Thing{}\n+}\n",
|
|
want: ClassFeature,
|
|
},
|
|
{
|
|
name: "no hunk falls back to feature",
|
|
sym: analysis.ChangedSymbol{ID: "a.go::Plain", Name: "Plain", Kind: "function", FilePath: "a.go"},
|
|
hunk: "",
|
|
want: ClassFeature,
|
|
},
|
|
}
|
|
g := graph.New()
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := ClassifyChange(g, tc.sym, tc.hunk)
|
|
if got != tc.want {
|
|
t.Fatalf("ClassifyChange(%s) = %q, want %q", tc.name, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestVerificationCommand covers the per-toolchain command derivation and the
|
|
// whole-tree fallback.
|
|
func TestVerificationCommand(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
targets []string
|
|
lang string
|
|
want string
|
|
}{
|
|
{
|
|
name: "go targets collapse to package dirs",
|
|
targets: []string{"internal/svc/handler_test.go", "internal/svc/other_test.go"},
|
|
lang: "go",
|
|
want: "go test ./internal/svc/...",
|
|
},
|
|
{
|
|
name: "go multiple dirs sorted",
|
|
targets: []string{"internal/b/b_test.go", "internal/a/a_test.go"},
|
|
lang: "go",
|
|
want: "go test ./internal/a/... ./internal/b/...",
|
|
},
|
|
{
|
|
name: "go no targets is whole module",
|
|
targets: nil,
|
|
lang: "go",
|
|
want: "go test ./...",
|
|
},
|
|
{
|
|
name: "lang inferred from extension",
|
|
targets: []string{"pkg/x/x_test.go"},
|
|
lang: "",
|
|
want: "go test ./pkg/x/...",
|
|
},
|
|
{
|
|
name: "python pytest",
|
|
targets: []string{"tests/test_foo.py"},
|
|
lang: "python",
|
|
want: "pytest tests/test_foo.py",
|
|
},
|
|
{
|
|
name: "typescript npm test",
|
|
targets: []string{"src/x.test.ts"},
|
|
lang: "",
|
|
want: "npm test",
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
got := VerificationCommand(tc.targets, tc.lang)
|
|
if got != tc.want {
|
|
t.Fatalf("VerificationCommand(%v,%q) = %q, want %q", tc.targets, tc.lang, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|