GoPLS Viewer

Home|gopls/go/internal/gccgoimporter/importer_test.go
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// Except for this comment, this file is a verbatim copy of the file
6// with the same name in $GOROOT/src/go/internal/gccgoimporter without
7// the import of "testenv".
8
9package gccgoimporter
10
11import (
12    "go/types"
13    "os"
14    "os/exec"
15    "path/filepath"
16    "regexp"
17    "runtime"
18    "strconv"
19    "testing"
20)
21
22type importerTest struct {
23    pkgpathnamewantwantval string
24    wantinits                    []string
25    gccgoVersion                 int // minimum gccgo version (0 => any)
26}
27
28func runImporterTest(t *testing.Timp Importerinitmap map[*types.Package]InitDatatest *importerTest) {
29    pkgerr := imp(make(map[string]*types.Package), test.pkgpath"."nil)
30    if err != nil {
31        t.Error(err)
32        return
33    }
34
35    if test.name != "" {
36        obj := pkg.Scope().Lookup(test.name)
37        if obj == nil {
38            t.Errorf("%s: object not found"test.name)
39            return
40        }
41
42        got := types.ObjectString(objtypes.RelativeTo(pkg))
43        if got != test.want {
44            t.Errorf("%s: got %q; want %q"test.namegottest.want)
45        }
46
47        if test.wantval != "" {
48            gotval := obj.(*types.Const).Val().String()
49            if gotval != test.wantval {
50                t.Errorf("%s: got val %q; want val %q"test.namegotvaltest.wantval)
51            }
52        }
53    }
54
55    if len(test.wantinits) > 0 {
56        initdata := initmap[pkg]
57        found := false
58        // Check that the package's own init function has the package's priority
59        for _pkginit := range initdata.Inits {
60            if pkginit.InitFunc == test.wantinits[0] {
61                found = true
62                break
63            }
64        }
65
66        if !found {
67            t.Errorf("%s: could not find expected function %q"test.pkgpathtest.wantinits[0])
68        }
69
70        // FIXME: the original version of this test was written against
71        // the v1 export data scheme for capturing init functions, so it
72        // verified the priority values. We moved away from the priority
73        // scheme some time ago; it is not clear how much work it would be
74        // to validate the new init export data.
75    }
76}
77
78// When adding tests to this list, be sure to set the 'gccgoVersion'
79// field if the testcases uses a "recent" Go addition (ex: aliases).
80var importerTests = [...]importerTest{
81    {pkgpath"pointer"name"Int8Ptr"want"type Int8Ptr *int8"},
82    {pkgpath"complexnums"name"NN"want"const NN untyped complex"wantval"(-1 + -1i)"},
83    {pkgpath"complexnums"name"NP"want"const NP untyped complex"wantval"(-1 + 1i)"},
84    {pkgpath"complexnums"name"PN"want"const PN untyped complex"wantval"(1 + -1i)"},
85    {pkgpath"complexnums"name"PP"want"const PP untyped complex"wantval"(1 + 1i)"},
86    {pkgpath"conversions"name"Bits"want"const Bits Units"wantval`"bits"`},
87    {pkgpath"time"name"Duration"want"type Duration int64"},
88    {pkgpath"time"name"Nanosecond"want"const Nanosecond Duration"wantval"1"},
89    {pkgpath"unicode"name"IsUpper"want"func IsUpper(r rune) bool"},
90    {pkgpath"unicode"name"MaxRune"want"const MaxRune untyped rune"wantval"1114111"},
91    {pkgpath"imports"wantinits: []string{"imports..import""fmt..import"}},
92    {pkgpath"importsar"name"Hello"want"var Hello string"},
93    {pkgpath"aliases"name"A14"gccgoVersion7want"type A14 = func(int, T0) chan T2"},
94    {pkgpath"aliases"name"C0"gccgoVersion7want"type C0 struct{f1 C1; f2 C1}"},
95    {pkgpath"escapeinfo"name"NewT"want"func NewT(data []byte) *T"},
96    {pkgpath"issue27856"name"M"gccgoVersion7want"type M struct{E F}"},
97    {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}"},
98    {pkgpath"nointerface"name"I"want"type I int"},
99    {pkgpath"issue29198"name"FooServer"gccgoVersion7want"type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"},
100    {pkgpath"issue30628"name"Apple"want"type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}"},
101    {pkgpath"issue31540"name"S"gccgoVersion7want"type S struct{b int; map[Y]Z}"},
102    {pkgpath"issue34182"name"T1"want"type T1 struct{f *T2}"},
103    {pkgpath"notinheap"name"S"want"type S struct{}"},
104}
105
106func TestGoxImporter(t *testing.T) {
107    testenv.MustHaveExec(t// this is to skip nacl, js
108    initmap := make(map[*types.Package]InitData)
109    imp := GetImporter([]string{"testdata"}, initmap)
110
111    for _test := range importerTests {
112        runImporterTest(timpinitmap, &test)
113    }
114}
115
116// gccgoPath returns a path to gccgo if it is present (either in
117// path or specified via GCCGO environment variable), or an
118// empty string if no gccgo is available.
119func gccgoPath() string {
120    gccgoname := os.Getenv("GCCGO")
121    if gccgoname == "" {
122        gccgoname = "gccgo"
123    }
124    if gpathgerr := exec.LookPath(gccgoname); gerr == nil {
125        return gpath
126    }
127    return ""
128}
129
130func TestObjImporter(t *testing.T) {
131    // This test relies on gccgo being around.
132    gpath := gccgoPath()
133    if gpath == "" {
134        t.Skip("This test needs gccgo")
135    }
136    if runtime.GOOS == "aix" {
137        // We don't yet have a debug/xcoff package for reading
138        // object files on AIX. Remove this skip if/when issue #29038
139        // is implemented (see also issue #49445).
140        t.Skip("no support yet for debug/xcoff")
141    }
142
143    verouterr := exec.Command(gpath"--version").CombinedOutput()
144    if err != nil {
145        t.Logf("%s"verout)
146        t.Fatal(err)
147    }
148    vers := regexp.MustCompile(`([0-9]+)\.([0-9]+)`).FindSubmatch(verout)
149    if len(vers) == 0 {
150        t.Fatalf("could not find version number in %s"verout)
151    }
152    majorerr := strconv.Atoi(string(vers[1]))
153    if err != nil {
154        t.Fatal(err)
155    }
156    minorerr := strconv.Atoi(string(vers[2]))
157    if err != nil {
158        t.Fatal(err)
159    }
160    t.Logf("gccgo version %d.%d"majorminor)
161
162    tmpdir := t.TempDir()
163    initmap := make(map[*types.Package]InitData)
164    imp := GetImporter([]string{tmpdir}, initmap)
165
166    artmpdir := t.TempDir()
167    arinitmap := make(map[*types.Package]InitData)
168    arimp := GetImporter([]string{artmpdir}, arinitmap)
169
170    for _test := range importerTests {
171        if major < test.gccgoVersion {
172            // Support for type aliases was added in GCC 7.
173            t.Logf("skipping %q: not supported before gccgo version %d"test.pkgpathtest.gccgoVersion)
174            continue
175        }
176
177        gofile := filepath.Join("testdata"test.pkgpath+".go")
178        if _err := os.Stat(gofile); os.IsNotExist(err) {
179            continue
180        }
181        ofile := filepath.Join(tmpdirtest.pkgpath+".o")
182        afile := filepath.Join(artmpdir"lib"+test.pkgpath+".a")
183
184        cmd := exec.Command(gpath"-fgo-pkgpath="+test.pkgpath"-c""-o"ofilegofile)
185        outerr := cmd.CombinedOutput()
186        if err != nil {
187            t.Logf("%s"out)
188            t.Fatalf("gccgo %s failed: %s"gofileerr)
189        }
190
191        runImporterTest(timpinitmap, &test)
192
193        cmd = exec.Command("ar""cr"afileofile)
194        outerr = cmd.CombinedOutput()
195        if err != nil {
196            t.Logf("%s"out)
197            t.Fatalf("ar cr %s %s failed: %s"afileofileerr)
198        }
199
200        runImporterTest(tarimparinitmap, &test)
201
202        if err = os.Remove(ofile); err != nil {
203            t.Fatal(err)
204        }
205        if err = os.Remove(afile); err != nil {
206            t.Fatal(err)
207        }
208    }
209}
210
MembersX
TestGoxImporter
TestGoxImporter.imp
TestGoxImporter.RangeStmt_5076.test
gccgoPath.gerr
importerTest.name
importerTest.wantval
runImporterTest.imp
runImporterTest.BlockStmt.got
TestObjImporter.minor
importerTest.gccgoVersion
runImporterTest.initmap
runImporterTest.err
TestObjImporter.imp
TestObjImporter.RangeStmt_6652.BlockStmt.out
regexp
runImporterTest.BlockStmt.BlockStmt.gotval
TestObjImporter.major
gccgoPath
TestObjImporter.err
TestObjImporter.initmap
TestObjImporter.arimp
TestObjImporter.RangeStmt_6652.BlockStmt.gofile
runImporterTest
runImporterTest.BlockStmt.found
TestGoxImporter.initmap
TestObjImporter.RangeStmt_6652.BlockStmt.err
TestObjImporter.t
TestObjImporter.gpath
TestObjImporter.arinitmap
TestObjImporter.RangeStmt_6652.BlockStmt.afile
TestGoxImporter.t
gccgoPath.gpath
TestObjImporter
gccgoPath.gccgoname
TestObjImporter.tmpdir
TestObjImporter.artmpdir
importerTest
importerTest.want
runImporterTest.BlockStmt.RangeStmt_1490.pkginit
TestObjImporter.RangeStmt_6652.test
TestObjImporter.RangeStmt_6652.BlockStmt._
TestObjImporter.RangeStmt_6652.BlockStmt.cmd
runImporterTest.pkg
runImporterTest.BlockStmt.obj
TestObjImporter.vers
runImporterTest.test
TestObjImporter.verout
TestObjImporter.RangeStmt_6652.BlockStmt.ofile
importerTest.pkgpath
importerTest.wantinits
runImporterTest.t
Members
X