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