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