chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
package languages
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/zzet/gortex/internal/graph"
|
||||
)
|
||||
|
||||
func TestGoStrings_StatsdMetricsExtracted(t *testing.T) {
|
||||
src := `package foo
|
||||
|
||||
type StatsdClient struct{}
|
||||
|
||||
func (c *StatsdClient) Increment(name string, tags []string, rate float64) error { return nil }
|
||||
func (c *StatsdClient) Gauge(name string, value float64, tags []string, rate float64) error { return nil }
|
||||
|
||||
func Run(c *StatsdClient) {
|
||||
c.Increment("orders.checkout.success", nil, 1)
|
||||
c.Gauge("server.memory.bytes", 12345, nil, 1)
|
||||
}
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
|
||||
strs := fix.nodesByKind[graph.KindString]
|
||||
if len(strs) != 2 {
|
||||
t.Fatalf("expected 2 KindString, got %d: %+v", len(strs), strs)
|
||||
}
|
||||
gotByValue := map[string]*graph.Node{}
|
||||
for _, n := range strs {
|
||||
gotByValue[n.Name] = n
|
||||
if ctx, _ := n.Meta["context"].(string); ctx != "metric" {
|
||||
t.Errorf("node %q: context = %q, want metric", n.Name, ctx)
|
||||
}
|
||||
want := "string::metric::" + n.Name
|
||||
if n.ID != want {
|
||||
t.Errorf("id = %q, want %q", n.ID, want)
|
||||
}
|
||||
}
|
||||
if gotByValue["orders.checkout.success"] == nil || gotByValue["server.memory.bytes"] == nil {
|
||||
t.Errorf("missing expected metric names: %v", gotByValue)
|
||||
}
|
||||
|
||||
emits := fix.edgesByKind[graph.EdgeEmits]
|
||||
if len(emits) != 2 {
|
||||
t.Errorf("expected 2 EdgeEmits, got %d", len(emits))
|
||||
}
|
||||
for _, e := range emits {
|
||||
if e.From != "pkg/foo.go::Run" {
|
||||
t.Errorf("emit from = %q, want pkg/foo.go::Run", e.From)
|
||||
}
|
||||
if ctx, _ := e.Meta["context"].(string); ctx != "metric" {
|
||||
t.Errorf("emit context = %q", ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_GenericMethodNamesIgnored(t *testing.T) {
|
||||
// Set / Inc / Add are too generic — would create false positives
|
||||
// against map and counter types — and are deliberately excluded.
|
||||
src := `package foo
|
||||
|
||||
type M struct{}
|
||||
func (m M) Set(k, v string) {}
|
||||
func (m M) Inc(k string) {}
|
||||
func (m M) Add(k string, n int) {}
|
||||
|
||||
func Run(m M) {
|
||||
m.Set("magic", "value")
|
||||
m.Inc("counter")
|
||||
m.Add("tally", 1)
|
||||
}
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
if got := fix.nodesByKind[graph.KindString]; len(got) != 0 {
|
||||
t.Errorf("expected no metric strings, got %d: %+v", len(got), got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_ErrorsNewAndFmtErrorf(t *testing.T) {
|
||||
src := `package foo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func A() error { return errors.New("user not found") }
|
||||
func B(id int) error { return fmt.Errorf("invalid id %d", id) }
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
|
||||
strs := fix.nodesByKind[graph.KindString]
|
||||
if len(strs) != 2 {
|
||||
t.Fatalf("expected 2 KindString, got %d: %+v", len(strs), strs)
|
||||
}
|
||||
gotByValue := map[string]*graph.Node{}
|
||||
for _, n := range strs {
|
||||
gotByValue[n.Name] = n
|
||||
if ctx, _ := n.Meta["context"].(string); ctx != "error_msg" {
|
||||
t.Errorf("node %q: context = %q, want error_msg", n.Name, ctx)
|
||||
}
|
||||
}
|
||||
if gotByValue["user not found"] == nil {
|
||||
t.Errorf("missing 'user not found': %v", gotByValue)
|
||||
}
|
||||
if gotByValue["invalid id %d"] == nil {
|
||||
t.Errorf("missing 'invalid id %%d': %v", gotByValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_HTTPRoutesExtracted(t *testing.T) {
|
||||
src := `package foo
|
||||
|
||||
type Mux struct{}
|
||||
func (m *Mux) HandleFunc(pattern string, h func()) {}
|
||||
func (m *Mux) Get(pattern string, h func()) {}
|
||||
|
||||
func Wire(m *Mux) {
|
||||
m.HandleFunc("/api/v1/users", nil)
|
||||
m.Get("/health", nil)
|
||||
m.HandleFunc("GET /api/v1/orders", nil)
|
||||
}
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
|
||||
strs := fix.nodesByKind[graph.KindString]
|
||||
if len(strs) != 3 {
|
||||
t.Fatalf("expected 3 KindString routes, got %d: %+v", len(strs), strs)
|
||||
}
|
||||
got := map[string]bool{}
|
||||
for _, n := range strs {
|
||||
got[n.Name] = true
|
||||
if ctx, _ := n.Meta["context"].(string); ctx != "route" {
|
||||
t.Errorf("node %q: context = %q, want route", n.Name, ctx)
|
||||
}
|
||||
}
|
||||
for _, want := range []string{"/api/v1/users", "/health", "GET /api/v1/orders"} {
|
||||
if !got[want] {
|
||||
t.Errorf("missing route %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_NonRouteStringSkipped(t *testing.T) {
|
||||
// Get/Post on map-like types — the looksLikeRoute filter should
|
||||
// keep these out of the route bucket.
|
||||
src := `package foo
|
||||
|
||||
type Cache struct{}
|
||||
func (c *Cache) Get(key string) string { return "" }
|
||||
|
||||
func Run(c *Cache) {
|
||||
_ = c.Get("user:42:profile")
|
||||
}
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
if got := fix.nodesByKind[graph.KindString]; len(got) != 0 {
|
||||
t.Errorf("expected no routes for cache.Get, got: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_SameMetricAcrossCallsDeduplicates(t *testing.T) {
|
||||
src := `package foo
|
||||
|
||||
type Client struct{}
|
||||
func (c *Client) Increment(name string) {}
|
||||
|
||||
func A(c *Client) { c.Increment("orders.success") }
|
||||
func B(c *Client) { c.Increment("orders.success") }
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
|
||||
strs := fix.nodesByKind[graph.KindString]
|
||||
if len(strs) != 1 {
|
||||
t.Fatalf("expected 1 KindString (deduplicated), got %d", len(strs))
|
||||
}
|
||||
emits := fix.edgesByKind[graph.EdgeEmits]
|
||||
if len(emits) != 2 {
|
||||
t.Errorf("expected 2 EdgeEmits (one per caller), got %d", len(emits))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_NodeIDForLongValueIsHashed(t *testing.T) {
|
||||
// 250 chars > 200-char threshold — should hash to keep IDs sane.
|
||||
long := strings.Repeat("a", 250)
|
||||
got := goStringNodeID(stringCtxErrorMsg, long)
|
||||
want := "string::error_msg::sha1:"
|
||||
if got[:len(want)] != want {
|
||||
t.Errorf("long-value id = %q, want prefix %q", got, want)
|
||||
}
|
||||
short := goStringNodeID(stringCtxMetric, "ok.short")
|
||||
if short != "string::metric::ok.short" {
|
||||
t.Errorf("short-value id = %q", short)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLooksLikeRoute(t *testing.T) {
|
||||
cases := map[string]bool{
|
||||
"/users": true,
|
||||
"/api/v1/orders": true,
|
||||
"GET /foo": true,
|
||||
"POST /bar": true,
|
||||
"": false,
|
||||
"plain": false,
|
||||
"user:42:profile": false,
|
||||
"orders.checkout.event": false,
|
||||
}
|
||||
for in, want := range cases {
|
||||
if got := looksLikeRoute(in, ""); got != want {
|
||||
t.Errorf("looksLikeRoute(%q) = %v, want %v", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLooksLikeRoute_FilesystemPathRejected(t *testing.T) {
|
||||
// A rooted literal that is a filesystem/config path must not survive the
|
||||
// route guard, even though the old shape heuristic accepted any "/..."
|
||||
// literal. A real route alongside it still passes.
|
||||
if looksLikeRoute("/etc/app.conf", "HandleFunc") {
|
||||
t.Errorf("looksLikeRoute(/etc/app.conf) accepted a config path as a route")
|
||||
}
|
||||
if looksLikeRoute("/Users/zzet/x", "Get") {
|
||||
t.Errorf("looksLikeRoute(/Users/zzet/x) accepted a home path as a route")
|
||||
}
|
||||
if !looksLikeRoute("/api/users", "Get") {
|
||||
t.Errorf("looksLikeRoute(/api/users) wrongly rejected a real route")
|
||||
}
|
||||
if !looksLikeRoute("GET /api/orders", "HandleFunc") {
|
||||
t.Errorf("looksLikeRoute(GET /api/orders) wrongly rejected a net/http route")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoStrings_FilesystemPathNotRoute(t *testing.T) {
|
||||
// A route-registration call whose literal is a filesystem/config path no
|
||||
// longer mints a route node, while a real route in the same file still does.
|
||||
src := `package foo
|
||||
|
||||
type Mux struct{}
|
||||
func (m *Mux) HandleFunc(pattern string, h func()) {}
|
||||
|
||||
func Wire(m *Mux) {
|
||||
m.HandleFunc("/etc/app.conf", nil)
|
||||
m.HandleFunc("/api/v1/users", nil)
|
||||
}
|
||||
`
|
||||
fix := runGoExtract(t, src)
|
||||
strs := fix.nodesByKind[graph.KindString]
|
||||
if len(strs) != 1 {
|
||||
t.Fatalf("expected exactly 1 route (the config path filtered), got %d: %+v", len(strs), strs)
|
||||
}
|
||||
if strs[0].Name != "/api/v1/users" {
|
||||
t.Errorf("expected surviving route /api/v1/users, got %q", strs[0].Name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user