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

171 lines
4.3 KiB
Go

package languages
import (
"testing"
"github.com/zzet/gortex/internal/graph"
)
func TestGoObservability_SlogPackageCall(t *testing.T) {
src := `package foo
import "log/slog"
func Run() {
slog.Info("user.signup", "id", 42)
slog.Error("payment.failed")
}
`
fix := runGoExtract(t, src)
events := fix.nodesByKind[graph.KindEvent]
if len(events) != 2 {
t.Fatalf("expected 2 KindEvent, got %d: %+v", len(events), events)
}
gotNames := map[string]bool{}
for _, e := range events {
gotNames[e.Name] = true
if e.ID != "event::log::"+e.Name {
t.Errorf("event id = %q (expected event::log::<name>)", e.ID)
}
if k, _ := e.Meta["event_kind"].(string); k != "log" {
t.Errorf("event_kind = %q", k)
}
}
if !gotNames["user.signup"] || !gotNames["payment.failed"] {
t.Errorf("missing event names: %v", gotNames)
}
emits := fix.edgesByKind[graph.EdgeEmits]
// emitGoObservabilityEvents now mirrors every event into a
// KindString context="log_message" registry node, so each log
// call emits two edges: one to the KindEvent, one to the
// KindString. Scope the count by target kind to keep the
// original assertion's intent (one event-side edge per call).
eventEmits := 0
stringEmits := 0
for _, e := range emits {
n := fix.nodesByID[e.To]
if n == nil {
continue
}
switch n.Kind {
case graph.KindEvent:
eventEmits++
case graph.KindString:
stringEmits++
}
}
if eventEmits != 2 {
t.Errorf("expected 2 EdgeEmits to KindEvent, got %d", eventEmits)
}
if stringEmits != 2 {
t.Errorf("expected 2 EdgeEmits to KindString log_message, got %d", stringEmits)
}
for _, e := range emits {
if e.From != "pkg/foo.go::Run" {
t.Errorf("emit from = %q", e.From)
}
if m, _ := e.Meta["method"].(string); m != "Info" && m != "Error" {
t.Errorf("method meta = %q", m)
}
}
}
func TestGoObservability_LoggerInstanceCall(t *testing.T) {
// Generic *Logger.Info(...) call — catches zap, zerolog, logrus,
// and most internal wrappers without per-provider plumbing.
src := `package foo
type Logger struct{}
func (l *Logger) Info(msg string, args ...any) {}
func Run(log *Logger) {
log.Info("auth.failed")
}
`
fix := runGoExtract(t, src)
events := fix.nodesByKind[graph.KindEvent]
if len(events) != 1 {
t.Fatalf("expected 1 event, got %d", len(events))
}
if events[0].Name != "auth.failed" {
t.Errorf("name = %q", events[0].Name)
}
}
func TestGoObservability_NonLiteralArgSkipped(t *testing.T) {
// Dynamic format strings don't produce a stable event name —
// agents who care about those can grep. The scanner skips them.
src := `package foo
import "log/slog"
func Run(msg string) {
slog.Info(msg)
}
`
fix := runGoExtract(t, src)
if got := len(fix.nodesByKind[graph.KindEvent]); got != 0 {
t.Errorf("non-literal arg should not produce KindEvent, got %d", got)
}
}
func TestGoObservability_DuplicateNameDeduplicates(t *testing.T) {
// Two emit sites for the same event name should produce one
// node and two edges, not two nodes.
src := `package foo
import "log/slog"
func A() { slog.Info("user.signup") }
func B() { slog.Info("user.signup") }
`
fix := runGoExtract(t, src)
events := fix.nodesByKind[graph.KindEvent]
if len(events) != 1 {
t.Errorf("expected 1 deduped event node, got %d", len(events))
}
// Each call site now emits two EdgeEmits — one to the KindEvent,
// one to the KindString log_message registry shadow. The dedup
// intent of the test is per-target-kind, so scope by kind.
eventEmits := 0
stringEmits := 0
for _, e := range fix.edgesByKind[graph.EdgeEmits] {
n := fix.nodesByID[e.To]
if n == nil {
continue
}
switch n.Kind {
case graph.KindEvent:
eventEmits++
case graph.KindString:
stringEmits++
}
}
if eventEmits != 2 {
t.Errorf("expected 2 emit edges to KindEvent (one per call site), got %d", eventEmits)
}
if stringEmits != 2 {
t.Errorf("expected 2 emit edges to KindString log_message (one per call site), got %d", stringEmits)
}
}
func TestGoObservability_NonLogMethodIgnored(t *testing.T) {
src := `package foo
type Counter struct{}
func (c *Counter) Add(name string, n int) {}
func Run(c *Counter) {
c.Add("api.requests", 1)
}
`
fix := runGoExtract(t, src)
if got := len(fix.nodesByKind[graph.KindEvent]); got != 0 {
t.Errorf("non-log method 'Add' should not produce KindEvent, got %d", got)
}
}