Skip to content

Commit 8b39106

Browse files
cuonglmmvdan
authored andcommitted
internal/reflectlite: add type mirror with reflect test
Add test to check that struct type in reflectlite is mirror of reflect. Note that the test does not check the field types, only check for number of fields and field name are the same. Updates #34486 Change-Id: Id5f9b26d35faec97863dd1fe7e5eab37d4913181 Reviewed-on: https://go-review.googlesource.com/c/go/+/199280 Run-TryBot: Cuong Manh Le <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent c7d81bc commit 8b39106

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package reflectlite_test
2+
3+
import (
4+
"fmt"
5+
"go/ast"
6+
"go/parser"
7+
"go/token"
8+
"os"
9+
"path/filepath"
10+
"runtime"
11+
"strings"
12+
"sync"
13+
"testing"
14+
)
15+
16+
var typeNames = []string{
17+
"rtype",
18+
"uncommonType",
19+
"arrayType",
20+
"chanType",
21+
"funcType",
22+
"interfaceType",
23+
"mapType",
24+
"ptrType",
25+
"sliceType",
26+
"structType",
27+
}
28+
29+
type visitor struct {
30+
m map[string]map[string]bool
31+
}
32+
33+
func newVisitor() visitor {
34+
v := visitor{}
35+
v.m = make(map[string]map[string]bool)
36+
37+
return v
38+
}
39+
func (v visitor) filter(name string) bool {
40+
for _, typeName := range typeNames {
41+
if typeName == name {
42+
return true
43+
}
44+
}
45+
return false
46+
}
47+
48+
func (v visitor) Visit(n ast.Node) ast.Visitor {
49+
switch x := n.(type) {
50+
case *ast.TypeSpec:
51+
if v.filter(x.Name.String()) {
52+
if st, ok := x.Type.(*ast.StructType); ok {
53+
v.m[x.Name.String()] = make(map[string]bool)
54+
for _, field := range st.Fields.List {
55+
k := fmt.Sprintf("%s", field.Type)
56+
if len(field.Names) > 0 {
57+
k = field.Names[0].Name
58+
}
59+
v.m[x.Name.String()][k] = true
60+
}
61+
}
62+
}
63+
}
64+
return v
65+
}
66+
67+
func loadTypes(path, pkgName string, v visitor) {
68+
fset := token.NewFileSet()
69+
70+
filter := func(fi os.FileInfo) bool {
71+
return strings.HasSuffix(fi.Name(), ".go")
72+
}
73+
pkgs, err := parser.ParseDir(fset, path, filter, 0)
74+
if err != nil {
75+
panic(err)
76+
}
77+
78+
pkg := pkgs[pkgName]
79+
80+
for _, f := range pkg.Files {
81+
ast.Walk(v, f)
82+
}
83+
}
84+
85+
func TestMirrorWithReflect(t *testing.T) {
86+
var wg sync.WaitGroup
87+
rl, r := newVisitor(), newVisitor()
88+
89+
for _, tc := range []struct {
90+
path, pkg string
91+
v visitor
92+
}{
93+
{".", "reflectlite", rl},
94+
{filepath.Join(runtime.GOROOT(), "src", "reflect"), "reflect", r},
95+
} {
96+
tc := tc
97+
wg.Add(1)
98+
go func() {
99+
defer wg.Done()
100+
loadTypes(tc.path, tc.pkg, tc.v)
101+
}()
102+
}
103+
wg.Wait()
104+
105+
if len(rl.m) != len(r.m) {
106+
t.Fatalf("number of types mismatch, reflect: %d, reflectlite: %d", len(r.m), len(rl.m))
107+
}
108+
109+
for typName := range r.m {
110+
if len(r.m[typName]) != len(rl.m[typName]) {
111+
t.Errorf("type %s number of fields mismatch, reflect: %d, reflectlite: %d", typName, len(r.m[typName]), len(rl.m[typName]))
112+
continue
113+
}
114+
for field := range r.m[typName] {
115+
if _, ok := rl.m[typName][field]; !ok {
116+
t.Errorf(`Field mismatch, reflect have "%s", relectlite does not.`, field)
117+
}
118+
}
119+
}
120+
}

0 commit comments

Comments
 (0)