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