1
2
3
4
5 package test
6
7 import (
8 "internal/testenv"
9 "os"
10 "path/filepath"
11 "regexp"
12 "strings"
13 "testing"
14 )
15
16
17
18
19
20
21 func TestShapeNameLength(t *testing.T) {
22 testenv.MustHaveGoBuild(t)
23 t.Parallel()
24
25
26
27
28 const src = `package p
29
30 type Big interface {
31 Eval(Context) Big
32 Inner() Big
33 ProgString() string
34 Rank() int
35 Sprint(*Config) string
36 String() string
37 shrink() Big
38 toType(string, *Config, int) Big
39 }
40
41 type Context struct{ _ int }
42 type Config struct{ _ int }
43
44 type Small interface{ Len() int }
45
46 type Holder[T any] struct{ v []T }
47
48 func (h *Holder[T]) Append(x T) { h.v = append(h.v, x) }
49
50 type BigStruct struct {
51 Field0, Field1, Field2, Field3, Field4 int
52 Field5, Field6, Field7, Field8, Field9 int
53 }
54
55 // Wrapper[T] instantiated with a hashed shape gives a shape whose own
56 // tag contains a '#', which shapifying it again has to cope with.
57 type Wrapper[T any] struct {
58 A, B, C, D, E T
59 F, G, H, I, J T
60 K, L, M, N, O T
61 }
62
63 func Nested[T any](x Wrapper[T]) {
64 var h Holder[Wrapper[T]]
65 h.Append(x)
66 }
67
68 var _ = Nested[Big]
69
70 var _ Holder[Big]
71 var _ Holder[Small]
72 var _ Holder[BigStruct]
73 var _ Holder[struct {
74 Alpha, Bravo, Charlie, Delta, Echo int
75 Foxtrot, Golf, Hotel, India, Juliett int
76 }]
77 `
78
79 dir := t.TempDir()
80 srcGo := filepath.Join(dir, "p.go")
81 if err := os.WriteFile(srcGo, []byte(src), 0644); err != nil {
82 t.Fatal(err)
83 }
84 obj := filepath.Join(dir, "p.o")
85
86 gotool := testenv.GoToolPath(t)
87 cmd := testenv.Command(t, gotool, "tool", "compile", "-p", "p", "-o", obj, srcGo)
88 if out, err := cmd.CombinedOutput(); err != nil {
89 t.Fatalf("%v: %v\n%s", cmd, err, out)
90 }
91
92 cmd = testenv.Command(t, gotool, "tool", "nm", obj)
93 out, err := cmd.CombinedOutput()
94 if err != nil {
95 t.Fatalf("%v: %v\n%s", cmd, err, out)
96 }
97 syms := string(out)
98
99
100
101
102 if !strings.Contains(syms, "go.shape.p.Big") {
103 t.Errorf("no go.shape.p.Big symbol in nm output\n%s", syms)
104 }
105 if strings.Contains(syms, "go.shape.interface { Eval(") {
106 t.Errorf("Big's full method set still appears in symbol names")
107 }
108
109 if !strings.Contains(syms, "go.shape.p.BigStruct") {
110 t.Errorf("no go.shape.p.BigStruct symbol in nm output\n%s", syms)
111 }
112
113
114
115
116 if regexp.MustCompile(`go\.shape\.Big\b`).MatchString(syms) {
117 t.Errorf("Big's shape is named without its package\n%s", syms)
118 }
119
120
121
122 if !regexp.MustCompile(`go\.shape\.[0-9a-f]{64}\b`).MatchString(syms) {
123 t.Errorf("no go.shape.<hash> symbol in nm output\n%s", syms)
124 }
125
126
127
128 if !strings.Contains(syms, "go.shape.interface { Len() int }") {
129 t.Errorf("Small's shape was hashed; want it spelled out\n%s", syms)
130 }
131
132
133
134
135 if !strings.Contains(syms, "go.shape.p.Wrapper[go.shape.p.Big]") {
136 t.Errorf("no nested go.shape.p.Wrapper[go.shape.p.Big] symbol in nm output\n%s", syms)
137 }
138
139
140
141
142
143
144 seen := map[string]bool{}
145 for _, line := range strings.Split(syms, "\n") {
146 f := strings.Fields(line)
147 if len(f) < 3 || f[1] != "T" {
148 continue
149 }
150 if name := f[2]; seen[name] {
151 t.Errorf("duplicate text symbol %s", name)
152 } else {
153 seen[name] = true
154 }
155 }
156 }
157
View as plain text