github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/go/internal/gccgoimporter/importer_test.go (about) 1 // Copyright 2013 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 gccgoimporter 6 7 import ( 8 "go/types" 9 "internal/testenv" 10 "io/ioutil" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "regexp" 15 "strconv" 16 "testing" 17 ) 18 19 type importerTest struct { 20 pkgpath, name, want, wantval string 21 wantinits []string 22 } 23 24 func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]InitData, test *importerTest) { 25 pkg, err := imp(make(map[string]*types.Package), test.pkgpath, ".", nil) 26 if err != nil { 27 t.Error(err) 28 return 29 } 30 31 if test.name != "" { 32 obj := pkg.Scope().Lookup(test.name) 33 if obj == nil { 34 t.Errorf("%s: object not found", test.name) 35 return 36 } 37 38 got := types.ObjectString(obj, types.RelativeTo(pkg)) 39 if got != test.want { 40 t.Errorf("%s: got %q; want %q", test.name, got, test.want) 41 } 42 43 if test.wantval != "" { 44 gotval := obj.(*types.Const).Val().String() 45 if gotval != test.wantval { 46 t.Errorf("%s: got val %q; want val %q", test.name, gotval, test.wantval) 47 } 48 } 49 } 50 51 if len(test.wantinits) > 0 { 52 initdata := initmap[pkg] 53 found := false 54 // Check that the package's own init function has the package's priority 55 for _, pkginit := range initdata.Inits { 56 if pkginit.InitFunc == test.wantinits[0] { 57 found = true 58 break 59 } 60 } 61 62 if !found { 63 t.Errorf("%s: could not find expected function %q", test.pkgpath, test.wantinits[0]) 64 } 65 66 // FIXME: the original version of this test was written against 67 // the v1 export data scheme for capturing init functions, so it 68 // verified the priority values. We moved away from the priority 69 // scheme some time ago; it is not clear how much work it would be 70 // to validate the new init export data. 71 } 72 } 73 74 var importerTests = [...]importerTest{ 75 {pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"}, 76 {pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1 + -1i)"}, 77 {pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"}, 78 {pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"}, 79 {pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"}, 80 {pkgpath: "conversions", name: "Bits", want: "const Bits Units", wantval: `"bits"`}, 81 {pkgpath: "time", name: "Duration", want: "type Duration int64"}, 82 {pkgpath: "time", name: "Nanosecond", want: "const Nanosecond Duration", wantval: "1"}, 83 {pkgpath: "unicode", name: "IsUpper", want: "func IsUpper(r rune) bool"}, 84 {pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"}, 85 {pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import"}}, 86 {pkgpath: "importsar", name: "Hello", want: "var Hello string"}, 87 {pkgpath: "aliases", name: "A14", want: "type A14 = func(int, T0) chan T2"}, 88 {pkgpath: "aliases", name: "C0", want: "type C0 struct{f1 C1; f2 C1}"}, 89 {pkgpath: "escapeinfo", name: "NewT", want: "func NewT(data []byte) *T"}, 90 {pkgpath: "issue27856", name: "M", want: "type M struct{E F}"}, 91 {pkgpath: "v1reflect", name: "Type", want: "type Type interface{Align() int; AssignableTo(u Type) bool; Bits() int; ChanDir() ChanDir; Elem() Type; Field(i int) StructField; FieldAlign() int; FieldByIndex(index []int) StructField; FieldByName(name string) (StructField, bool); FieldByNameFunc(match func(string) bool) (StructField, bool); Implements(u Type) bool; In(i int) Type; IsVariadic() bool; Key() Type; Kind() Kind; Len() int; Method(int) Method; MethodByName(string) (Method, bool); Name() string; NumField() int; NumIn() int; NumMethod() int; NumOut() int; Out(i int) Type; PkgPath() string; Size() uintptr; String() string; common() *commonType; rawString() string; runtimeType() *runtimeType; uncommon() *uncommonType}"}, 92 {pkgpath: "nointerface", name: "I", want: "type I int"}, 93 {pkgpath: "issue29198", name: "FooServer", want: "type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"}, 94 } 95 96 func TestGoxImporter(t *testing.T) { 97 testenv.MustHaveExec(t) // this is to skip nacl, js 98 initmap := make(map[*types.Package]InitData) 99 imp := GetImporter([]string{"testdata"}, initmap) 100 101 for _, test := range importerTests { 102 runImporterTest(t, imp, initmap, &test) 103 } 104 } 105 106 // gccgoPath returns a path to gccgo if it is present (either in 107 // path or specified via GCCGO environment variable), or an 108 // empty string if no gccgo is available. 109 func gccgoPath() string { 110 gccgoname := os.Getenv("GCCGO") 111 if gccgoname == "" { 112 gccgoname = "gccgo" 113 } 114 if gpath, gerr := exec.LookPath(gccgoname); gerr == nil { 115 return gpath 116 } 117 return "" 118 } 119 120 func TestObjImporter(t *testing.T) { 121 // This test relies on gccgo being around. 122 gpath := gccgoPath() 123 if gpath == "" { 124 t.Skip("This test needs gccgo") 125 } 126 127 verout, err := exec.Command(gpath, "--version").CombinedOutput() 128 if err != nil { 129 t.Logf("%s", verout) 130 t.Fatal(err) 131 } 132 vers := regexp.MustCompile(`([0-9]+)\.([0-9]+)`).FindSubmatch(verout) 133 if len(vers) == 0 { 134 t.Fatalf("could not find version number in %s", verout) 135 } 136 major, err := strconv.Atoi(string(vers[1])) 137 if err != nil { 138 t.Fatal(err) 139 } 140 minor, err := strconv.Atoi(string(vers[2])) 141 if err != nil { 142 t.Fatal(err) 143 } 144 t.Logf("gccgo version %d.%d", major, minor) 145 146 tmpdir, err := ioutil.TempDir("", "") 147 if err != nil { 148 t.Fatal(err) 149 } 150 initmap := make(map[*types.Package]InitData) 151 imp := GetImporter([]string{tmpdir}, initmap) 152 153 artmpdir, err := ioutil.TempDir("", "") 154 if err != nil { 155 t.Fatal(err) 156 } 157 arinitmap := make(map[*types.Package]InitData) 158 arimp := GetImporter([]string{artmpdir}, arinitmap) 159 160 for _, test := range importerTests { 161 // Support for type aliases was added in GCC 7. 162 if test.pkgpath == "aliases" || test.pkgpath == "issue27856" || test.pkgpath == "issue29198" { 163 if major < 7 { 164 t.Logf("skipping %q: not supported before gccgo version 7", test.pkgpath) 165 continue 166 } 167 } 168 169 gofile := filepath.Join("testdata", test.pkgpath+".go") 170 if _, err := os.Stat(gofile); os.IsNotExist(err) { 171 continue 172 } 173 ofile := filepath.Join(tmpdir, test.pkgpath+".o") 174 afile := filepath.Join(artmpdir, "lib"+test.pkgpath+".a") 175 176 cmd := exec.Command(gpath, "-fgo-pkgpath="+test.pkgpath, "-c", "-o", ofile, gofile) 177 out, err := cmd.CombinedOutput() 178 if err != nil { 179 t.Logf("%s", out) 180 t.Fatalf("gccgo %s failed: %s", gofile, err) 181 } 182 183 runImporterTest(t, imp, initmap, &test) 184 185 cmd = exec.Command("ar", "cr", afile, ofile) 186 out, err = cmd.CombinedOutput() 187 if err != nil { 188 t.Logf("%s", out) 189 t.Fatalf("ar cr %s %s failed: %s", afile, ofile, err) 190 } 191 192 runImporterTest(t, arimp, arinitmap, &test) 193 194 if err = os.Remove(ofile); err != nil { 195 t.Fatal(err) 196 } 197 if err = os.Remove(afile); err != nil { 198 t.Fatal(err) 199 } 200 } 201 202 if err = os.Remove(tmpdir); err != nil { 203 t.Fatal(err) 204 } 205 }