github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/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 "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 // TODO when the dust clears, figure out what this should actually test. 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 // On some mobile builders, the test binary executes on a machine without a 95 // complete GOROOT source tree. 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 }