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

67 lines
2.5 KiB
Go

package contracts
import (
"testing"
)
// TestExtractGoShape_NestedAnonymousStruct guards the regression
// where the line-based extractor hoisted fields of an inline
// anonymous struct into the outer struct's field list — producing
// duplicate names when the parent and substruct shared field names
// (e.g. dashboardSnapshot's outer `Repos` / `Caveats` clashing with
// the embedded Stats.Repos / Stats.Caveats fields). React then
// rendered two children with the same key and warned in the
// dashboard.
//
// Fix: track brace depth and only emit fields at depth 0 (direct
// members of the outer struct). Nested-struct fields are dropped
// rather than mis-attributed.
func TestExtractGoShape_NestedAnonymousStruct(t *testing.T) {
src := []byte(`type dashboardSnapshot struct {
Stats struct {
TotalNodes int ` + "`json:\"total_nodes\"`" + `
TotalEdges int ` + "`json:\"total_edges\"`" + `
Repos int ` + "`json:\"repos\"`" + `
Caveats int ` + "`json:\"caveats\"`" + `
Version string ` + "`json:\"version\"`" + `
} ` + "`json:\"stats\"`" + `
Kinds []kvEntry ` + "`json:\"kinds\"`" + `
Languages []kvEntry ` + "`json:\"languages\"`" + `
Repos []repoEntry ` + "`json:\"repos\"`" + `
Activity []changeEvent ` + "`json:\"activity\"`" + `
Caveats []caveatEntry ` + "`json:\"caveats\"`" + `
Processes []processEntry ` + "`json:\"processes\"`" + `
}
`)
shape := extractGoShape(src, 1, 16)
if shape == nil {
t.Fatal("expected non-nil shape")
}
seen := map[string]int{}
for _, f := range shape.Fields {
seen[f.Name]++
}
for name, count := range seen {
if count > 1 {
t.Errorf("field %q appears %d times — duplicate names hoist nested struct into parent", name, count)
}
}
// Each top-level field must show up exactly once. We don't assert
// the parent `stats` is present (the regex doesn't match the
// `Stats struct {` line — that's an acceptable under-report; the
// alternative — over-reporting with duplicates — broke the React
// tree).
wantTopLevel := []string{"kinds", "languages", "repos", "activity", "caveats", "processes"}
for _, name := range wantTopLevel {
if seen[name] != 1 {
t.Errorf("top-level field %q expected once, got %d", name, seen[name])
}
}
// Inner Stats fields MUST NOT be hoisted (they collide with the
// outer ones). Specifically `total_nodes` is unique to the inner
// struct, so its presence proves the bug recurred.
if seen["total_nodes"] > 0 {
t.Errorf("inner Stats.TotalNodes leaked into outer shape (hoisting regression)")
}
}