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 "rtype",
23 "uncommonType",
24 "arrayType",
25 "chanType",
26 "funcType",
27 "interfaceType",
28 "mapType",
29 "ptrType",
30 "sliceType",
31 "structType",
32 }
33
34 type visitor struct {
35 m map[string]map[string]bool
36 }
37
38 func newVisitor() visitor {
39 v := visitor{}
40 v.m = make(map[string]map[string]bool)
41
42 return v
43 }
44 func (v visitor) filter(name string) bool {
45 for _, typeName := range typeNames {
46 if typeName == name {
47 return true
48 }
49 }
50 return false
51 }
52
53 func (v visitor) Visit(n ast.Node) ast.Visitor {
54 switch x := n.(type) {
55 case *ast.TypeSpec:
56 if v.filter(x.Name.String()) {
57 if st, ok := x.Type.(*ast.StructType); ok {
58 v.m[x.Name.String()] = make(map[string]bool)
59 for _, field := range st.Fields.List {
60 k := fmt.Sprintf("%s", field.Type)
61 if len(field.Names) > 0 {
62 k = field.Names[0].Name
63 }
64 v.m[x.Name.String()][k] = true
65 }
66 }
67 }
68 }
69 return v
70 }
71
72 func loadTypes(path, pkgName string, v visitor) {
73 fset := token.NewFileSet()
74
75 filter := func(fi fs.FileInfo) bool {
76 return strings.HasSuffix(fi.Name(), ".go")
77 }
78 pkgs, err := parser.ParseDir(fset, path, filter, 0)
79 if err != nil {
80 panic(err)
81 }
82
83 pkg := pkgs[pkgName]
84
85 for _, f := range pkg.Files {
86 ast.Walk(v, f)
87 }
88 }
89
90 func TestMirrorWithReflect(t *testing.T) {
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", len(r.m), len(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