github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/not-internal/reflectlite/reflect_mirror_test.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflectlite_test 6 7 import ( 8 "fmt" 9 "go/ast" 10 "go/parser" 11 "go/token" 12 "os" 13 "path/filepath" 14 "runtime" 15 "strings" 16 "sync" 17 "testing" 18 ) 19 20 var typeNames = []string{ 21 "rtype", 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 os.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 reflectDir := filepath.Join(runtime.GOROOT(), "src", "reflect") 91 if _, err := os.Stat(reflectDir); os.IsNotExist(err) { 92 // On some mobile builders, the test binary executes on a machine without a 93 // complete GOROOT source tree. 94 t.Skipf("GOROOT source not present") 95 } 96 97 var wg sync.WaitGroup 98 rl, r := newVisitor(), newVisitor() 99 100 for _, tc := range []struct { 101 path, pkg string 102 v visitor 103 }{ 104 {".", "reflectlite", rl}, 105 {reflectDir, "reflect", r}, 106 } { 107 tc := tc 108 wg.Add(1) 109 go func() { 110 defer wg.Done() 111 loadTypes(tc.path, tc.pkg, tc.v) 112 }() 113 } 114 wg.Wait() 115 116 if len(rl.m) != len(r.m) { 117 t.Fatalf("number of types mismatch, reflect: %d, reflectlite: %d", len(r.m), len(rl.m)) 118 } 119 120 for typName := range r.m { 121 if len(r.m[typName]) != len(rl.m[typName]) { 122 t.Errorf("type %s number of fields mismatch, reflect: %d, reflectlite: %d", typName, len(r.m[typName]), len(rl.m[typName])) 123 continue 124 } 125 for field := range r.m[typName] { 126 if _, ok := rl.m[typName][field]; !ok { 127 t.Errorf(`Field mismatch, reflect have "%s", relectlite does not.`, field) 128 } 129 } 130 } 131 }